一个可重复隔离级别的事务A,另一个可重复隔离级别的事务B,A要更新B锁住的行,此时A只能进入等待状态,等A获得行锁时,要更新的数据的值是什么呢?
事务启动的两种方式
- 一致性视图在执行第一个快照读语句时创建;
- 一致性视图在执行start transaction with consistent snapshot 时创建。
两种视图
- view视图:在执行查询语句时生成,为查询语句定义的虚拟表。
- 一致性视图:InnoDB 在实现 MVCC使用的就是一致性读视图(consistent read view),用于支持 RC(Read Committed,读提交)和 RR(Repeatable Read,可重复读)隔离级别的实现。
举例
数据库中存有两条数据:
id | k |
---|---|
1 | 1 |
2 | 2 |
- 事务A在执行start transaction with consistent snapshot 时启动,故查询结果k=1;
- 事务B在执行start transaction with consistent snapshot 时启动,但在执行update语句时,会再执行一次查询,此时查询结果k=2,当执行完update语句时,再执行下一条语句得到的结果k=3;
- 事务C没有显式地使用 begin/commit,是在执行update语句时才启动。
MVCC
- transition id:每个事务有一个唯一的事务ID,是在事务开始时生成的;
- row trx_id:每次事务更新时,会生成一个新的数据版本,并将transition id赋值给row trx_id;
- 一行记录可能存在多个版本,每个版本有自己的 row trx_id。
V1、V2、V3 并不是物理上真实存在的,而是每次需要的时候根据当前版本和 undo log 计算出来的。比如,需要 V2 的时候,就是通过 V4 依次执行 U3、U2 算出来。
InnoDB 为每个事务构造了一个数组,用来保存这个事务启动瞬间,当前启动了但还没提交的所有事务 ID。数组里面事务 ID 的最小值记为低水位,当前系统里面已经创建过的事务 ID 的最大值加 1 记为高水位。
一致性视图:由视图数组和高水位组成。
数据版本的可见性规则:row trx_id和一致性视图的对比结果。
一个数据版本,对于一个事务视图来说,除了自己的更新总是可见以外,有三种情况: - 版本未提交,不可见;
- 版本已提交,但是是在视图创建后提交的,不可见;
- 版本已提交,而且是在视图创建前提交的,可见。
本文为《MySQL实战45讲》学习笔记