【MySQL】MVCC原理分析 源码级理解

就是看不惯有的面试官,看了网上什么乱七八糟的说法,自己的认知都是有问题的,一个劲说。出一篇文章。

必要说明

行文参考

操作手册:MySQL Manual
源码手册:MySQL Source Code Documentation
项目源码:mysql-server

解决的问题

这里需要特别说明的是,MVCC解决的是 READ COMMITTD 、REPEATABLE READ 隔离级别下幻读与不可重复读的并发问题。 目的是 不用在串行隔离级别下解决幻读,避免采用锁。

实现要素

实现MVCC(Multiversion Concurrency Control)多版本并发控制,抽象地说,需要一个类似于控制器的玩意,需要版本信息,需要版本对应的数据(数据是有的,这里其实需要的是 版本与数据的关系)。这就引出了MVCC实现的三个要素:

  • ReadView
  • Transaction ID, Roll pointer
  • Undo Log

其中 Undo Log 自然有,Roll pointer 指向了Undo Log版本链的头节点。这里关注一下ReadView、Roll pointer。

transaction ID 和 roll pointer

这要从行格式说起

Mysql官方文档关于行格式的介绍,这里关于行格式的解释比较详细了,建议不清楚的直接看官网,csdn很多不准确的说法抄来抄去的。

这里以 Compact 行格式为例,关注一下行格式中的隐藏列(隐藏列可能有三个,这里假如我们的表有可以充当ROW_ID的列):

在这里插入图片描述

Records in the clustered index contain fields for all user-defined columns. In addition, there is a 6-byte transaction ID field and a 7-byte roll pointer field.

  • transaction ID:每个事务都有唯一的事务ID,事务中操作的每个数据的transaction ID会记录该条事务的事务ID。这是个很朴素一对多存储方式。
  • roll pointer:相当于一个指向 undo log 链表的头指针,每次操作数据的信息都被记录在链表里(这玩意儿叫版本链)。

在这里插入图片描述

ReadView

网上一堆关于 ReadView 的说法,大多是不准确的(小声说:抄来抄去的有啥意思)。

插播一段:这里之前被 java岗 的面试官问,ReadView是个啥,怎么实现的,来来来,给你看看是怎么实现的。就喜欢你这种刨根问底的面试官。

这里是官方文档的描述:

关于 ReadView 的官方定义 定义

个人翻译:ReadView 记录的是,在读一致性要求下,不应被展示的一些操作所属的事务ID。

值得一提的是,这里声明了友元类MVCC。也就是说,ReadView 对 MVCC 是开放状态的。

在这里插入图片描述

trx_ids

一句话说明:当前系统中的活跃事务列表,底层存储用的时vector容器。

因为整个 ReadView 都是围绕这个展开,所以首先认识一下这个类内部的内部容器ids_t:

用 trx_ids_t定义的,trx_ids又是一堆ids_t的容器。ids_t 是事务的唯一标志(我没记错的话应该有张事务表,就是由这个类型的数据落盘存储的)。

在这里插入图片描述
在这里插入图片描述

定义在ReadView中,又将ReadView指定为友元类。注释说模拟了vector容器,实际上是 在这里插入图片描述

我这里挑出来关键的几个属性:

creator_trx_id

一句话说明:这个是记录创建 ReadView 的 事务ID。
在这里插入图片描述

外部赋值是通过 其友元类 MVCC 中静态方法完成:

例如在设置 读写模式时
在这里插入图片描述.

在创建了新的 ReadView 对象时,显然prepare需要刷新 m_creator_trx_id
在这里插入图片描述

low_limit_id 与 up_limit_id

low_limit_id 是最大,up_limit_id 是最小

在这里插入图片描述

这里文档注释说得很清楚。

  • low_limit_id 大于等于此值不让读,即:当前的ID小于等于 low_limit_id 才可以读。这本来就指的是当前系统事务的最大值。
  • up_limit_id 小于此值让读。这个就是 最小活跃事务。

UML就不画了,抽象一下这几个变量之间的关系。

在这里插入图片描述

MVCC 过程分析

首先抽象一下,一条sql在mysql-server中执行顺序:解析、优化、执行、返回;这里着重抓取,区分隔离级别之后的动作。

// TODO

READ COMMITTED的MVCC

REPEATABLE READ的MVCC

// TODO

源码级理解

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

MVCC(Multi-Version Concurrency Control,多版本并发控制)是MySQL数据库中实现事务隔离别的一种机制。MVCC基于数据库中数据的版本来实现并发控制。每个事务在读取数据时,都会读取该数据的一个版本,而不是读取最新的数据。 MVCC的实现原理是:在每个记录(行)的后面,保存了该记录的创建时间和过期时间(或删除时间)。在读取数据时,MySQL会根据事务的隔离别以及事务启动时的时间戳来选择合适的版本。具体来说,MySQL会根据以下规则选择版本: - 读未提交(Read Uncommitted):读取最新版本的数据,不考虑其他事务的并发操作。 - 读已提交(Read Committed):读取已经提交的数据的最新版本,不读取未提交的数据。 - 可重复读(Repeatable Read):在同一个事务中,读取的数据版本是该事务启动时的版本。在这个事务中,其他事务对该数据的更新不会影响该事务读取的数据版本。 - 串行化(Serializable):在同一个事务中,读取的数据版本是该事务启动时的版本。在这个事务中,其他事务对该数据的更新不会影响该事务读取的数据版本。同时,该事务对数据的更新也不会影响其他事务的并发操作。 当一个事务需要更新数据时,MySQL会创建该数据的一个新版本,并将新版本的创建时间设置为当前时间。同时,MySQL会将旧版本的过期时间设置为当前时间。 MVCC机制可以提高数据库的并发性能,但也会增加数据库的存储空间和I/O负载。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值