天天看点

mysql事务隔离REPEATABLE-READ防止幻读问题

事务隔离级别:

===========================================================================================

       隔离级别               脏读(Dirty Read)          不可重复读(NonRepeatable Read)     幻读(Phantom Read) 

===========================================================================================

未提交读(Read uncommitted)        可能                            可能                       可能

已提交读(Read committed)          不可能                          可能                        可能

可重复读(Repeatable read)          不可能                          不可能                     可能

可串行化(Serializable )                不可能                          不可能                     不可能

===========================================================================================

·未提交读(Read Uncommitted):允许脏读,也就是可能读取到其他会话中未提交事务修改的数据

·提交读(Read Committed):只能读取到已经提交的数据。Oracle等多数数据库默认都是该级别 (不重复读)

·可重复读(Repeated Read):可重复读。在同一个事务内的查询都是事务开始时刻一致的,InnoDB默认级别。在SQL标准中,该隔离级别消除了不可重复读,但是还存在幻象读

·串行读(Serializable):完全串行化的读,每次读都需要获得表级共享锁,读写相互都会阻塞

mysql默认事务隔离级别是 REPEATABLE-READ,并且是可以防止幻读的,很多地方也有提到这点,但事实真的是这样吗?先看个例子:

事务A 事务B
mysql事务隔离REPEATABLE-READ防止幻读问题
mysql事务隔离REPEATABLE-READ防止幻读问题
mysql事务隔离REPEATABLE-READ防止幻读问题
我们插入一条数据
mysql事务隔离REPEATABLE-READ防止幻读问题
mysql事务隔离REPEATABLE-READ防止幻读问题
这个时候是查不到,事务隔离
mysql事务隔离REPEATABLE-READ防止幻读问题
更新了3行数据,什么鬼,查询明明只有两条
mysql事务隔离REPEATABLE-READ防止幻读问题
刚才事务B插入的数据也被更新了!
mysql事务隔离REPEATABLE-READ防止幻读问题

事务A居然更新了另外一个事务插入的数据,说好的防止幻读呢,所以mysql可重复读实现并不是严格意义上的si隔离。

MVCC机制行的可见条件很简单,可以总结为两句话:

  1. 对不同事务,插入事务已提交,删除事务未提交(update可以看做先删除后插入);
  2. 对本事务,插入的statement发生在自己之前,删除的statement未发生或在自己之后;

更新操作看做是先删除再插入,删除发生在事务A更新之前,导致条件2可见,事务A更新了事务B插入数据

参考了这篇文章(参考内容:地址 ),里面也对比了其他数据库可重复读隔离级别

sql