MySQL InnoDB基于MVCC实现了非锁定读(我们也称之为快照读,因为它是基于快照实现的),极大地提交了数据库的并发性。在InnoDB中默认的读取方式都是非锁定读,即不会占用和等待表或记录上的锁。
Innodb基于一致性视图consistent read view实现MVCC,我们通常称之为快照读,在事务开始的时候,需要对MySQL整个库创建一份“快照”,但是这里的快照在实现上并不是对整个库拷贝一份数据,这样显然是不现实的。
其实InnoDB是基于ReadView这个数据结构来实现快照的,ReadView可用用来计算某一条记录对于当前事务是不是可见。
ReadView数据结构中有一下几个核心属性:
对应mysql-server源码位置:storage/innobase/include/read0types.h
-
活跃事务集合 m_ids
当前快照被创建时,活跃(已启动但未提交)的事务集合,
-
高水位 m_low_limit_id
当前系统中的事务的最大id值加一,即下一个开启的事务的id,大于等于该id的事务都是在该快照创建之后开启的事务
-
低水位 m_up_limit_id
当前活跃事务的最小id,小于该id的事务都是已经提交的事务
那么如何判断一条记录对于当前事务是不是可见。
InnoDB对于每一条记录都有维护一个data_trx_id的隐藏列,表示最新更改该行记录的事务id。
InnoDB只需要取出该记录的data_trx_id,基于ReadView数据结构就可以计算出是否可见:
- data_trx_id ≥ 高水位,不可见,表示这个数据是由将来的事务更新的
- data_trx_id < 低水为,可见,表示这个数据是由已经提交的事务更新的
- 介于高水位与低水位之间
- 如果在活跃事务集合中,表示尚未提交的事务,不可见
- 如果不在,表示事务已经提交了,可见
对于读已提交和可重复读,其一致性快照的定义是不一样的:
- 读已提交,对于事务中每一次快照读都会重新计算一下一致性事务
- 可重复读,只会在事务开始的第一次快照读创建一致性事务,后续的读取都会使用这个一致性事务
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END