以下内容全部基于innodb。
虽然下面有很多概念很浅显,但还是要解释一下
什么是幻读?
当一个事务在多次查询中,发现了一行不是在当前事务中添加的数据。出现这种问题就叫做幻读。
关于四种隔离级别
未提交读(Read Uncommitted):允许脏读,也就是可能读取到其他会话中未提交事务修改的数据
提交读(Read Committed):只能读取到已经提交的数据。解决了脏读,未解决不可重复读问题。
可重复读(Repeated Read):可重复读。在同一个事务内的查询都是事务开始时刻一致的。该隔离级别消除了不可重复读,但是还存在幻象读。
串行读(Serializable):完全串行化的读,每次读都需要获得表级共享锁,读写相互都会阻塞
其实,传统的rr隔离级别下,是存在幻读问题的,但mysql 下真的会有幻读问题吗?先说明一下我的结论:
mysql在rr隔离级别下一定程度上解决了幻读问题。 由于innodb引擎下存在当前读和快照读的概念。
在当前读的情况下,mysql通过配置可以采用记录锁(Record Lock)+间隙锁(Gap Lock),让其他插入或删除事务死锁,达到解决幻读问题。
在快照读的情况下,mysql如果不更新插入记录,那么由于是读取的旧版本记录,对于其他事务插入数据不可见,从而达到了解决幻读问题。但是如果当前事务更新记录(包括不可见的),会去读取最新版本内容,从而看到了其他事务插入的数据,产生幻读。
个人理解,当前读跟快照读的区分,就是因为mysql innodb mvcc,普通的查询就是快照读。
此处建议去看一下mvcc原理,涉及比较多,不再此处解释。
什么是当前读
以下操作就是采用当前读,会读取当前数据的最新记录,同时加锁
select ... lock in share mode
select ... for update
insert
update
delete
什么是快照读
最普通的查询操作,查询的时候不包括lock in share mode跟 for update
select * from test
就先介绍这么多,作为自己备忘,看到的小伙伴可以去自己证实以下我的结论。实践出真知