前言
Mysql是一种关系型数据库被被大家广泛的使用,而当它在高并发的情况下,会产生一些脏读、不可重复读、幻读等问题,可能网上博客介绍这种问题的文章也是遍地都是,但是还是想写一篇加深印象和总结一下。
事务的特性
事务4大特性(ACID) :原子性、一致性、隔离性、持久性。
原子性:事务中的全部操作在数据库中是不可分割的,要么全部完成,要么均不执行.
一致性:几个并行执行的事务,其执行结果必须与按某一顺序串行执行的结果相一致。
隔离性:事务的执行不受其他事务的干扰,当数据库被多个客户端并发访问时,隔离它们的操作,防止出现:脏读、幻读、不可重复读。
持久性:对于任意已提交事务,系统必须保证该事务对数据库的改变不被丢失。
事务的隔离级别
READ UNCOMMITTED:可以读取未提交的数据,未提交的数据称之为脏数据又称之为脏读,在RU模式下幻读、不可重复读和脏读都是被允许的。
READ COMMITTED:只能读取已经提交的数据,幻读和不可重复读被允许,不允许脏读,RC级别解决了脏读问题。
REPEATABLE READ:同一个事务中多次执行同一个select读取到的数据没有变化(这时候就是解决了不可重复读不可重复读仅限于查询),RR级别解决了不可重复读,但有幻读的问题。
SERIALIZABLE:串行化在这个级别下幻读、不可重复读、脏读都是不被允许的。
看起来是不是只要选择串行化级别,什么异常读取都不会发生,但是串行级别下会造成性能下降,串行化它会导致表级锁,对所有的记录都不能修改,而且不支持多个事务同时对一张表进行修改,查询时没问题的。
实践环境
实践mysql版本5.7.25,存储引擎Innodb
RR级别的幻读实践
mysql设置当前会话的隔离级别为RR,set session transaction isolation level REPEATABLE READ
当第二个事务提交后,在第一个事务中是查询不到id_text为2的数据,但是在第一个事务中插入id_text为2的时候报主键重复异常,这就叫幻读,明显查询不到但是修改时候却告诉我数据存在。
这个级别下是不存在不可重复读取的,可以验证第三步和第五步查询的数据是一致的,如果是不一致的将有不可重复读的问题。
RU级别的脏读实践
mysql设置当前会话的隔离级别为RU,set session transaction isolation level READ UNCOMMITTED
要说mysql隔离级别哪种最可怕无非就是RU,因为它可以读取别人未提交的数据简称脏读,如果第一个事务正常的提交不出任何问题,可能会正常,但是假如我进行Rollback操作,事务二读取出来的数据就是脏数据,将会影响业务操作会造成意想不到的灾难。
RC级别的不可重复读实践
mysql设置当前会话的隔离级别为RU,set session transaction isolation level READ COMMITTED
不可重复读的表现在同一个事务中,两个相同的插叙语句查询出来的数据不一致,这是因为两个查询语句中间包含了其他事务的修改数据提交,导致第一次和第二次查询数据不一致,它和脏读的区别就是,它读取的数据必须是事务执行成功后的数据,而脏读是读取事务还没进行提交的数据。
在第六步和第八步就证明了脏读和不可重复读的区别,如果是脏读第六步查询出来的数据与第四步查询的数据就不一致。