MVCC总结
1 MVCC是什么
-
可以认为MVCC是行锁的一个变种,大都实现了非阻塞的读操作,写操作也只锁定了必要的行。
2 MVCC能干什么
-
通过保存数据在某个时间点的快照来实现的,根据事务开始时间的不同,每个事务对于同一张表,同一时刻看到的数据可能是不同的。
-
是隔离级别 RR 和RC实现隔离性的手段
3 MVCC原理
3.1 undo log
-
事务号和回滚指针 -
事务1,更新一行记录的时候 锁行 然后要把老记录放到undo log,同时改行的回滚指针要指向undo log中的改行之前版本的记录
![]()
-
事务2 更新改行,该行记录每个版本形成一个undo 链。
![]()
-
在Innodb中存在purge线程,它会查询那些比现在最老的活动事务还早的undo log,并删除它们,从而保证undo log文件不至于无限增长。
-
undo log分insert和update undo log,因为insert时,原始的数据并不存在,所以回滚时把insert undo log丢弃即可
3.2 事务链表
MySQL中的事务在开始到提交这段过程中,都会被保存到一个叫trx_sys的事务链表中,这是一个基本的链表结构:

事务链表中保存的都是还未提交的事务,事务一旦被提交,则会被从事务链表中摘除。处在trx_sys中的事务,也叫做活跃事务 active transaction
3.3 READ VIEW
read view是mvcc最重要的一个概念,如果说mvcc不说read view,恐怕面试是通不过的,说不到点子上。
read view是干什么的呢?上面可知MVCC实现了多个并发事务更新同一行记录会时产生多个记录版本,那问题来了,新开始的事务如果要查询这行记录,应该获取到哪个版本呢?就需要read view来解决行的可见性问题。

low_limit_id 前者表示事务id大于此值的行记录都不可见。事务号的最大值,最高水位。
up_limit_id 后者表示事务id小于此值的行记录都可见。事务号的最小值,最低水位。
所有数据行上DATA_TRX_ID小于up_trx_id的记录,说明修改该行的事务在当前事务开启之前都已经提交完成,所以对当前事务来说,都是可见的。而对于DATA_TRX_ID大于low_trx_id的记录,说明修改该行记录的事务在当前事务之后,所以对于当前事务来说是不可见的。至于位于(up_trx_id, low_trx_id)中间的事务是否可见,这个需要根据不同的事务隔离级别来确定。对于RC的事务隔离级别来说,对于事务执行过程中,已经提交的事务的数据,对当前事务是可见的,也就是说上述图中,当前事务运行过程中,trx1~4中任意一个事务提交,对当前事务来说都是可见的;而对于RR隔离级别来说,事务启动时,已经开始的事务链表中的事务的所有修改都是不可见的,所以在RR级别下,low_trx_id基本保持与up_trx_id相同的值即可。
对于RR隔离级别来说,事务一旦开启,这个事务链trx_sys就不会再改变了。所以一行数据的DATA_TRX_ID只要不小于up_limit_id,就一定不可见。需要顺着roll pointer找之前的版本。
对于行记录上的DATA_TRX_ID如果在up_limit_id 和 low_limit_id 之间的,需要进一步的判断。
总结:
MVCC就是为了解决读写冲突而搞出来的一套简化查询的机制,对于一个普通的select,是不加锁的非阻塞读取。而实现这种功能就有三点
1 行的隐藏列 undolog 指针和 已提交的事务ID
2 未提交的事务链表
3 read view
只要搞懂这三点,就能明白mvcc了
事务号和回滚指针

浙公网安备 33010602011771号