深入浅出的对MVCC底层原理进行剖析

MVCC多版本并发控制机制

隔离性就是靠MVCC(Multi-Version Concurrency Control)机制来保证的,对一行数据的读和写两个操作默认是不会通过加锁互斥来保证隔离性,避免了频繁加锁互斥,而在串行化隔离级别为了保证较高的隔离性是通过将所有操作加锁互斥来实现的。

Mysql在读已提交可重复读隔离级别下都实现了MVCC机制。

MVCC多版本并发控制机制实现原理

undo日志版本链read view机制

undo日志版本链与read view机制详解

undo日志版本链是指一行数据被多个事务依次修改过后,在每个事务修改完后,Mysql会保留修改前的数据undo回滚日志,并且用两个隐藏字段trx_id和roll_pointer把这些undo日志串联起来形成一个历史记录版本链。如图所示

这里我通过一个account表来演示原理过程,这里是account表的数据图

 

一切就绪进入我们的解读之路!我们以可重复读隔离级别为例,我们都知道在这种隔离级别下,读是快照读,而写是当前写,为什么呢?让我们一起来看看吧!

可重复读隔离级别,当事务开启,执行任何查询sql时会生成当前事务的一致性视图read-view,该视图在事务结束之前永远都不会变化(如果是读已提交隔离级别在每次执行查询sql时都会重新生成read-view,记住这句话,这也就是两个隔离级别的一个最大的差别),这个视图由执行查询时所有未提交事务id数组(数组里最小的id为min_id)和已创建的最大事务id(max_id)组成,事务里的任何sql查询结果需要从对应版本链里的最新数据开始逐条跟read-view做比对从而得到最终的快照结果。

例如,以我的例子为例,他的一个readview[100,200] 300就是,那么我们可以划分三个段:

然后,我们可以按照他的版本链比对规则逐个版本进行对比,就可以很清晰明白MVCC保证隔离性的原理了!

版本链比对规则:

1. 如果 row 的 trx_id 落在绿色部分( trx_id可见的;

2. 如果 row 的 trx_id 落在红色部分( trx_id>max_id ),表示这个版本是由将来启动的事务生成的,是不可见的(若 row 的 trx_id 就是当前自己的事务是可见的);

3. 如果 row 的 trx_id 落在黄色部分(min_id

    a. 若 row 的 trx_id 在视图数组中,表示这个版本是由还没提交的事务生成的,不可见(若 row 的 trx_id 就是当前自己的事务是可见的);

    b. 若 row 的 trx_id 不在视图数组中,表示这个版本是已经提交了的事务生成的,可见。

看到这里,小伙伴们,可能还一脸懵,没关系,我们通过上面的account表例子来演示一遍,你就知道上面说的原理了。

首先,我们有开启三个事务,事务100和200是对无关表进行修改操作,只是为了开启事务,事务300对我们的account表进行修改操作,讲balance修改为500,并提交。此时我们另开一个窗口查询account表的余额值,很明显结果是500,我们都知道,但是之后事务100对account表进行修改,将500改为1000,我们再去查为什么还是500呢,相信大家在刚开始学的时候都会有这个疑问,接下里我来带着大家来看看吧!

此时我们的回滚日志的情况如上图,我们要想知道此时去读accout表读的数据是哪一个,就需要用到 前面所提到的版本链比对规则了,我们需要得出readView也就是在我们第一次select时事务情况,事务100 200处于活跃状态,加入到视图数组中,而事务300已提交,但是却是最大的事务,作为max-id。

我们根据版本链比对规则先看第一条,事务100也就是落在了黄色区间,而他又属于视图数组readview[100,200]中的元素,那么

根据这条规则也就是不可见,继续比对

又是事务100,同理继续往上去找第一个符合的

 事务300,也是在黄色区间,但是它却不再视图数组中,也就是符合这条规则,可见,即查询结果为500

写到这里想必大家已经大概清楚它的一个流程了叭,别急,我在来掰扯掰扯读已提交隔离级别 ,他为什么读的总是最新的结果,就是因为它每次执行select语句的时候都要重新生成readview,那么已经被提交的事务就不可能再视图数组中,那么它无论是属于绿色区域还是黄色区域都是符合可见的条件。

  • 42
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值