什么是MVCC
多版本并发控制:读取数据时通过一种类似快照的方式将数据保存下来,这样读锁就和写锁不冲突了,不同的事务session会看到自己特定版本的数据,版本链
MVCC只在 READ COMMITTED 和 REPEATABLE READ 两个隔离级别下工作。其他两个隔离级别够和MVCC不兼容,因为 READ UNCOMMITTED 总是读取最新的数据行,而不是符合当前事务版本的数据行。而 SERIALIZABLE 则会对所有读取的行都加锁。
聚簇索引记录中有两个必要的隐藏列:
-
trx_id::用来存储每次对某条聚簇索引记录进行修改的时候的事务id。
-
roll_pointer:每次对哪条聚簇索引记录有修改的时候,都会把老版本写入undo日志中。这个roll_pointer就是存了一个指针,它指向这条聚簇索引记录的上一个版本的位置,通过它来获得上一个版本的记录信息。(注意插入操作的undo日志没有这个属性,因为它没有老版本)
已提交读和可重复读的区别就在于它们生成ReadView的策略不同。
-
开始事务时创建readview,readView维护当前活动的事务id,即未提交的事务id,排序生成一个数组
-
访问数据,获取数据中的事务id (获取的是事务id最大的记录),对比readview:
-
如果在readview的左边 (比readview都小),可以访问 (在左边意味着该事务已经提交)
-
如里在readview的右边(比readview都大) 或者就在readview中,不可以访问,获取roll_pointer,取上一版本
重新对比(在右边意味着,该事务在readview生成之后出现,在readview中意味着该事务还未提交) -
已提交读隔离级别下的事务在每次查询的开始都会生成一个独立的ReadView,而可重复读隔离级别则在第一次读的时候生成一个ReadView,之后的读都复用之前的ReadView。
-
这就是Mysql的MVCC,通过版本链,实现多版本,可并发读·写,写-读。通过ReadView生成策略的不同实现不同的隔离级别。