MVCC底层原理原理

MVCC 多版本并发控制机制


MVCC 主要通过 read-view 机制(一致性视图)和 undo 日志版本链对比机制,来实现不同事务根据数据版本链的不同规则读取同一条数据的在版本链上不同版本的数据。

多版本: 有多个事务的时候,每个事务都可以通过 undo 日志链读取到符合自己规则的数据。
并发: 多个事务对同一行数据的读和写操作并发执行,不阻塞。

例如在 RR(可重复读) 隔离级别,同样的 sql 查询语句在一个事务中结果都相同,即使别的事务修改了数据也不会对这个 sql 语句的查询结果产生影响。这个隔离性就是靠 MVCC 来实现。

MySQL 在 RC(读已提交),RR(可重复读) 隔离级别都实现了 MVCC 机制。

undo 日志版本链

开启事务,执行了更新表数据的语句,这条更新后的结果会记录在 undo 日志版本链中,更新语句即使未提交也会被记录到版本链中,例如下图中的事务 id 为 4 的那条数据就还没被提交。

版本链中还有隐藏的两个字段,trx_id(事务id),roll_pointer(回滚指针),不是第一条记录的回滚指针指向前一条记录,是第一条的记录回滚指针指向 undo 日志。

undo 回滚日志


read-view 机制(一致性视图)

在 RC 和 RR 隔离级别,执行查询 sql 语句会生成当前事务的 read-view,这个视图由当前查询时所有未提交的事务组成的事务id数组以及已提交的最大事务 id 组成。

如何判断数据是否可见?
1、如果事务 id 小于事务id数组中最小值,说明这个事务已经提交了,数据可见;
2、如果事务 id 大于已提交的最大事务 id ,说明这个事务还未生成,数据不可见。
3、以上两种情况都不符合的话,并且事务 id 在未提交事务id数组范围内,说明这个事务未提交,数据不可见;
4、否则说明事务已提交,数据可见。

不同隔离级别生成视图规则也不一样。在 RC 隔离级别下,同一个事务,每执行一次查询语句都会生成新的视图;在 RR 隔离级别下,同一个事务,只会使用由第一次查询语句生成的视图。

read-view 机制(一致性视图)和 undo 日志版本链使用案例

假设在 RR 隔离级别下, read-view 的值是 [100, 200] , 300。100 和 200 是未提交的事务,300 是已提交的事务中最大的事务 id。
可见性算法

搭配上面 undo 回滚日志来看。

1、新增一个事务 A,查询 id 为 1 的那行数据,通过版本链,观察事务 id 为 300 的那条记录,满足数据可见的条件,可得到 balance 值为 500 这个结果。
2、把事务 100 提交了,版本链中已包含事务 100 的数据,此时表中 id 为 1 的 balance 值为 1000。
3、事务 A 再次查询 id 为 1 的那行数据, 会从版本链最下面的那一行开始做匹配,即事务 id 为 100 的记录开始做匹配,此时 read-view 的值不变,仍是 [100, 200] , 300,因为 100 在数组中,所以事务 id 为100 的数据均不可见,又到了事务 id 为 300 的那条记录,数据可见,因此 balance 的值仍为 500。
4、此时新增一个事务 B,仍是查询 id 为 1 的那行数据,因为此时事务 id 为 100 的事务提交了,所以事务 B 的一致性视图是 [200], 300,根据 undo 日志版本链可得出此时 balance 的值为 1000。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值