【MVCC】MVCC之通过readview判断事务读取哪个版本(通俗易懂,一文详解!!)

MVCC的实现原理

mvcc的实现,基于undolog版本链readview。(具体就如下图)

在 MySQL 存储的数据中,MySQL 会默认添加一些额外的隐含字段(Hidden Field),包括 trx_idroll_pointer 等字段。这些字段大多数是用于支持事务和数据恢复等功能。

  • trx_id:是一个系统自动生成的、递增的整数,用于标识当前操作是在哪个事务中执行的。每开始一个新的事务,事务 ID 就会自增 1。因为事务 ID 是系统自动生成的,所以我们一般不需要对其进行手动修改。
  • roll_pointer:是一个指针,用来定位上一个版本的数据。当你对一条记录进行修改时,MySQL 会在内部为该记录创建一份副本并保存到 redo log 中,同时记录下这个副本在 redo log 中的位置,这就是 roll_pointer 所表示的内容。如果发生了回滚操作,MySQL 会通过 roll_pointer 来查找对应记录的上一个版本,并将其恢复回去。

有了这么多的版本之后,当有一个select查询的时候,具体查询的哪个版本呢?

readview读视图来帮我们解决这个问题

当我们用select读取数据时,这一时刻的数据会有很多个版本(例如上图有四个版本),但我们并不知道读取哪个版本,这时就靠readview来对我们进行读取版本的限制,通过readview我们才知道自己能够读取哪个版本

在事务select查询数据时,就会构造一个readview,里面就记录了该条数据版本链的一些统计值,这样在后续查询处理时就无需遍历所有版本链了。

在一个readview快照中具体包括以下这些字段:

对readview中的参数做一些解释

**m_ids:**活跃的事务就是指还没有commit的事务(会像一个集合一样展示出那些活跃【未提交】的事务)。

**max_trx_id:**例如m_ids中的事务id为(1,2,3),那么下一个应该分配的事务id就是4,max_trx_id就是4。

creator_trx_id:当前执行select读这个操作的事务的id。

readview具体判断版本链中的哪个版本可用(重点!)

四步查找规则------

第一步:判断该版本是否由当前事务创建

creator_trx_id=【当前版本trx_id】,意味着读取自己修改的数据,当然可以直接访问。如果不等于当前版本的trx_id则跳到第二步

第二步:【当前版本trx_id】是否小于min_trx_id

【当前版本trx_id】<min_trx_id,说明该版本在生成readview之前已经提交,可以直接访问。如果不是则进行第三步

第三步:【当前版本trx_id】是否大于max_trx_id

【当前版本trx_id】>max_trx_id,说明该版本在生成readview之后才开启,肯定不能被当前事务访问,所以此时就不需要进行第四步再去遍历判断下一个版本。如果当前版本的事务id小于最大事务id则可以继续进行第四步

第四步:min_trx_id<【当前版本trx_id】<max_trx_id

如果当前版本不在活跃事务列表当中,则意味着创建readview的时候,该版本已经被提交,可以直接访问。

如果在活跃事务列表当中,则按照版本链遍历去判断下一个版本,直到找到首个符合要求的版本。

从上到下分别为(1)(2)(3)(4),再依次进行一遍解释,可以加深一遍印象

trx_id表示要读取的事务id

(1)如果要读取的事务id等于进行读操作的事务id,说明是我读取我自己创建的记录,那么为什么不可以呢。

(2)如果要读取的事务id小于最小的活跃事务id,说明要读取的事务已经提交,那么可以读取。

(3)max_trx_id表示生成readview时,分配给下一个事务的id,如果要读取的事务id大于max_trx_id,说明该id已经不在该readview版本链中了,故无法访问。

(4)m_ids中存储的是活跃事务的id,如果要读取的事务id不在活跃列表,那么就可以读取,反之不行。

mvcc如何实现RC和RR的隔离级别

(1)RC 的隔离级别下,每个快照读 都会生成并获取最新的readview

(2)RR 的隔离级别下,只有在同一个事务第一个快照读 才会创建readview ,之后的每次快照读都使用的同一个readview ,所以每次的查询结果都是一样的

相关推荐
梵法利亚13 分钟前
Ubuntu-docker安装mysql
mysql·ubuntu·docker
FreemanGordon38 分钟前
Java volatile 关键字
java
北京_宏哥39 分钟前
《手把手教你》系列基础篇(九十三)-java+ selenium自动化测试-框架设计基础-POM设计模式实现-上篇(详解教程)
java·前端·selenium
北京_宏哥1 小时前
《手把手教你》系列基础篇(九十二)-java+ selenium自动化测试-框架设计基础-POM设计模式简介(详解教程)
java·selenium·前端工程化
炬火初现1 小时前
Etcd的安装与使用
数据库·etcd
当归10241 小时前
微服务与消息队列RabbitMQ
java·微服务
IT猿手1 小时前
2025最新群智能优化算法:云漂移优化(Cloud Drift Optimization,CDO)算法求解23个经典函数测试集,MATLAB
开发语言·数据库·算法·数学建模·matlab·机器人
Lx3521 小时前
《从头开始学java,一天一个知识点》之:循环结构:for与while循环的使用场景
java·后端
程序员爱钓鱼1 小时前
Go 语言高效连接 MySQL 数据库:从入门到实战
后端·mysql·go
Cache技术分享1 小时前
15. Java 如何声明一个变量来引用数组
java·前端