更多博客请见 我的语雀知识库
不可重复读是由其他事务的更新操作造成的,而幻读则是由本事务的更新操作造成的

不可重复读指的是:某事务第一次读取变量A的值为1,其它事务将其更新为2。后这个某事务读到了其它事务对A更新后的值2。前后读取的这个变量的值不相同。

而幻读指的是:某事务第一次读取变量A=1的行数据 条数 是五条,之后再次读取变量A=1的行数据 条数 ,发现变成了六条。前后数据条数不一致

列举一个幻读场景:
事务X第一次读取一批量的行数据1,2,3,4,5,共有五条数据。之后事务Y新增一行数据6。后事务X对6这行数据update了, 再去读这一批数据的值,发现读到的是1,2, 3 , 4 , 5, 6,共有六条数据。多了个一条数据,和第一次的结果不相同

2024.05.16update:以上文中幻读的场景举例,某事务在快照读的情况下,确实查不到新增的数据,但是,update语句是不管什么readview快照的,它是当前读。update语句一定读取的是最新的数据。如果某事务对第六行数据做了update操作(这时,某事务根据readview是查不到这行数据的,但是可以对它update。这很违和,但确实存在),update结束之后,第六行数据对应的事务id就变成了某事务本身。后续再根据readview查数据,就可以把第六行数据查出来了。 所以,可重复读级别下没有完全解决幻读问题。

如何在可重复读级别下,尽可能的解决幻读呢?(以下情况默认Innodb引擎)
那就是在创建事务之后,立刻执行 select … for update 这类当前读的语句,因为它会对记录加临键锁(组合锁),从而避免其他事务插入一条新记录。
而普通的select语句是通过MVCC读的,不涉及到锁。