对于InnoDB,聚簇索引记录中包含3个隐藏的列:
- ROW ID:隐藏的自增ID,如果没有主键,InnoDB会自动按ROWID产生一个聚集索引树。
- 事务ID:记录最后一次修改该记录的事务ID。
- 回滚指针:指向这条记录的上一个版本。
我们拿上面的例子,对应解释一下MVCC的实现原理,如下图:
如图,首先 insert 语句向表 t1 中插入了一条数据,a字段为1,b字段为1,ROW ID也为1,事务ID
假设为1,回滚指针假设为null。当执行update t1 set b=666 where a=1时,大致步骤如下:
- 数据库会对满足 a=1 的行加排他锁;
- 然后将原记录复制到 undo 表空间中;
- 修改 b 字段的值为 666,修改事务 ID 为2;
- 通过隐藏的回滚指针指向 undo log 中的历史记录;
- 事务提交,释放前面对满足 a=1 的行所加的排他锁。
总结:
InnoDB每一行数据都有一个隐藏的回滚指针,用于指向该行修改前的最后一个历史版本,这个历史版本存放在 undo log 中。
如果要执行更新操作,会将原记录放入 undo log 中,并通过隐藏的回滚指针指向 undo log 中的原记录。其它事务此时需要查询时,就是查询 undo log 中这行数据的最后一个历史版本。
MVCC最大的好处是读不加锁,读写不冲突,极大地增加了MySQL的并发性。通过MVCC,保证了事务的隔离性。