MySQL 系列 幻读

MySQL 技术内幕:InnoDB存储引擎

Posted by lichao modified on May 21, 2020

MySQL 的 RR 隔离级别通过 MVCC + Next-key Locks 解决幻读问题

幻读

在一次事务中,多次查询之后,结果集的个数不一致的情况叫做幻读。而多出来或者少的哪一行被叫做幻行

在高并发数据库系统中,需要保证事务与事务之间的隔离性,还有事务本身的一致性

解决方法

在快照读读情况下, MySQL 通过 MVCC 来避免幻读。

在当前读读情况下, MySQL 通过 next-key lock 来避免幻读。

1
2
select * from t where a=1; # 属于快照读
select * from t where a=1 lock in share mode; # 属于当前读

不能把 快照读 和 当前读 得到的结果不一样这种情况认为是幻读,这是两种不同的使用。所以可认为 MySQL 的 RR 级别是解决了幻读的。

多版本并发控制(MVCC)(快照读/一致性读)

多数数据库都实现了多版本并发控制,并且都是靠保存数据快照来实现的。

事务每次取数据的时候都会取创建版本小于当前事务版本的数据,以及过期版本大于当前版本的数据。

普通的 select 就是快照读。

1
select * from T where number = 1;

原理:将历史数据存一份快照,所以其他事务增加与删除数据,对于当前事务来说是不可见的。

相关文档-MVCC

next-key lock(当前读)

next-key lock 包含两部分:

  • 记录锁(行锁)
  • 间隙锁 记录锁是加在索引上的锁,间隙锁是加在索引之间的。

相关文档-锁

参考文献

聊聊MVCC和Next-key Locks

MySQL 到底是怎么解决幻读的?