了解这个问题前需要先重复理解MVCC的工作原理,本文便不多赘述
说幻读是事务A执行两次 select 操作得到不的数据集,即 select 1得到 10 条记录,select 2得到 15 条记录,这其实并不是幻读,既然第一次和第二次读取的不一致,那不还是不可重复读吗,所以这是不可重复读的一种。
正确的理解应该是幻读,并不是说两次读取获取的结果集不同,幻读侧重的方面是某一次的 select 操作得到的结果所表征的数据状态无法支撑后续的业务操作。更为具体一些:select 某记录是否存在,不存在,准备插入此记录,但执行 nsed时发现此记录已存在,无法插入,此时就发生了幻读。
MVCC解决了部分幻读问题,还有其他特殊情况:
发生幻读问题:
1、虽然在可重复读的隔离级别下,READVIEW复用第一次生成的,使得大部分情况下不会出现幻读问题(即前后读取不一致),但是MVCC读取规则是依靠于 READVIEW+UNDOLOG版本链。在下面样例中,使用了update操作执行了当前读,而这个当前读使得UNDOLOG版本链最上面的当前事务ID修改为了A事务的ID。所以在读取规则中当前事务ID=creator_id,所以事务A可以读取到最新的数据版本,从而产生了幻读。
2.执行快照读才会走MVCC机制,保证可重复读。而执行当前读则是利用锁机制读取最新的数据,所以数据前后不一致
而在RR的隔离级别下,使用MVCC+锁机制可以解决幻读问题。锁机制阻塞其他事务的update操作,所以不会产生幻读问题。