【MySQL】InnoDB引擎 —— MVCC —— readview介绍

ReadView(读视图)是快照读 SQL执行时MVCC提取数据的依据,记录并维护系统当前活跃的事务 (未提交的)id。

因为我们知道,快照读在读取的时候并不是读取最新的记录,它读取的有可能是历史版本;刚才我们已经介绍了undo log日志所形成的版本链,在版本链中所产生的这些记录都是历史记录,我们快照读在执行的时候,那么到底读取哪一个历史记录呢?就是有ReadView来决定的,因为在ReadView中它会记录并维护系统当前活跃的事务id,这种获取的事务id指的是未提交的事务id。

ReadView中包含了四个核心字段:

字段含义
m_ids当前活跃的事务ID集合
min_trx_id最小活跃事务ID
max_trx_id预分配事务ID,当前最大事务ID + 1(因为事务ID是自增的)
creator_trx_idReadView创建者的事务ID

而在readview中就规定了版本链数据的访问规则:

trx_id 代表当前undolog版本链对应事务ID。

在获取历史版本数据的时候,到底获取的时哪一个历史版本,就是拿当前事务的id,和刚才ReadView中的四个属性进行比对。

条件是否可以访问说明
trx_id == creator_trx_id可以访问该版本成立,说明数据是当前这个事务更改的。
我刚刚更新的记录,那肯定是可以读取出来的。
trx_id < min_trx_id可以访问该版本成立,说明数据已经提交了。
因为当前事务ID比最小的活跃事务ID还小。
trx_id > max_trx_id不可以访问该版本成立,说明该事务是在 ReadView 生成后才开始的。
min_trx_id <= trx_id <= max_trx_id如果 trx_id 不在 m_ids 中,可以访问该版本成立,说明数据已经提交。

不同的隔离级别,生成ReadView的时机不同:

  • READ COMMITTED :在事务中每一次执行快照读时生成ReadView。
  • REPEATABLE READ:仅在事务中第一次执行快照读时生成ReadView,后续复用该ReadView。

RC级别原理分析

RC隔离级别下,在事务中每一次执行快照读时生成ReadView。

我们就来分析事务5中,两次快照读读取数据,是如何获取数据的?

在事务5中,查询了两次id为30的记录,由于隔离级别为Read Committed,所以每一次进行快照读 都会生成一个ReadView,那么两次生成的ReadView如下。

image-20240720225649276

那么这两次快照读在获取数据时,就需要根据所生成的ReadView以及ReadView的版本链访问规则, 到undolog版本链中匹配数据,最终决定此次快照读返回的数据。

A. 先来看第一次快照读具体的读取过程:

image-20240720225737080

image-20240720225747843

在进行匹配时,会从undo log的版本链,从上到下进行挨个匹配:

先匹配

image-20240720225804031

这条记录,这条记录对应的 trx_id为4,也就是将4带入右侧的匹配规则中。 ①不满足 ②不满足 ③不满足 ④也不满足 , 都不满足,则继续匹配undo log版本链的下一条。

再匹配第二条

image-20240720225827240

,这条 记录对应的trx_id为3,也就是将3带入右侧的匹配规则中。①不满足 ②不满足 ③不满足 ④也不满足 ,都不满足,则继续匹配undo log版本链的下一条。

再匹配第三条

image-20240720225845672

,这条记 录对应的trx_id为2,也就是将2带入右侧的匹配规则中。①不满足 ②满足 终止匹配,此次快照 读,返回的数据就是版本链中记录的这条数据。


B. 再来看第二次快照读具体的读取过程:

image-20240720225909633

image-20240720225918087

在进行匹配时,会从undo log的版本链,从上到下进行挨个匹配:

先匹配

image-20240720225939746

这条记录,这条记录对应的 trx_id为4,也就是将4带入右侧的匹配规则中。 ①不满足 ②不满足 ③不满足 ④也不满足 , 都不满足,则继续匹配undo log版本链的下一条。

再匹配第二条

image-20240720230006558

,这条记录对应的trx_id为3,也就是将3带入右侧的匹配规则中。①不满足 ②满足 。终止匹配,此次快照读,返回的数据就是版本链中记录的这条数据。


RR级别原理分析

RR隔离级别下,仅在事务中第一次执行快照读时生成ReadView,后续复用该ReadView。 而 RR 是可重复读,在一个事务中,执行两次相同的select语句,查询到的结果是一样的。

那MySQL是如何做到可重复读的呢? 我们简单分析一下就知道了

image-20240720230055766

我们看到,在RR隔离级别下,只是在事务中第一次快照读时生成ReadView,后续都是复用该 ReadView,那么既然ReadView都一样, ReadView的版本链匹配规则也一样, 那么最终快照读返回的结果也是一样的。

所以呢,MVCC的实现原理就是通过 InnoDB表的隐藏字段、UndoLog 版本链、ReadView来实现的。 而 MVCC + 锁,则实现了事务的隔离性。

而一致性则是由redolog 与 undolog保证。一致性指的是数据在执行之前和执行之后是一致的,也就是说这个事务如果执行失败,需要全部回滚,保证数据执行前后一致;事务如果正常提交,我一定要保证这个数据一定是更新过来了的。

image-20240720230113984

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值