幻读:同一个查询在不同时刻查询到的结果集不同
场景:
(1):对于快照读来说—在可重复读隔离级别下,事务 A 第一次执行普通的 select 语句时生成了一个 ReadView,之后事务 B 向表中新插入了一条 id = 6 的记录并提交。接着,事务 A 对 id = 6 这条记录进行了更新操作,在这个时刻,这条新记录的 trx_id 隐藏列的值就变成了事务 A 的事务 id,之后事务 A 再使用普通 select 语句去查询这条记录时就可以看到这条记录了,于是就发生了幻读。
首先update,delete,insert操作都会将当前事务id回写到记录行中,如果在同一个事务里一开始没有显式的使用当前读方式,而是在update,insert,delete后再次进行快照读,都有可能在mvcc模式下产生幻读。
(2)对于当前读来说—如果事务开启后,并没有执行当前读,而是先快照读,然后这期间如果其他事务插入了一条记录,那么事务后续使用当前读进行查询的时候,就会发现两次查询的记录条目就不一样了,所以就发生幻读。
要避免这类特殊场景下发生幻读的现象的话,就是尽量在开启事务之后,马上执行 select ... for update 这类当前读的语句,因为它会对记录加 next-key lock,从而避免其他事务插入一条新记录。