当前位置: 首页 > news >正文

MVCC原理解析

由于事务的隔离性是由MVCC和锁(排他锁)来保证的,所以MVCC也尤为重要

MVCC全称Multi-Version Concurrency Control,多版本并发控制,事务的无锁的实现方式,指维护一个数据的多个版本,使得读写操作没有冲突

MVCC允许多个事务同时读取同一行数据,而不会彼此阻塞,每个事务看到的数据版本是该事务开始时的数据版本。这意味着,如果其他事务在此期间修改了数据,正在运行的事务仍然看到的是它开始时的数据状态,从而实现了非阻塞读操作。

对于「读提交」和「可重复读」隔离级别的事务来说,它们是通过 Read View 来实现的,它们的区别在于创建 Read View 的时机不同,大家可以把 Read View 理解成一个数据快照,就像相机拍照那样,定格某一时刻的风景。

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

同时,读的概念又分为两种,一种是当前读,一种是快照读

  • 当前读

读取的是记录的最新版本,读取时还要保证其他并发事务不能修改当前记录,会对读取的记录进行加锁。对于我们日常的操作,如select...lock in share mode(共享锁),select ...for update update insert delete(排它锁)都是一种当前读

  • 快照读

简单的select(不加锁)就是快照读,读取的是记录数据的可见版本,有可能是历史数据.不加锁,是非阻塞读

  • Read Committed:每次select,都生成一个快照读
  • Repeatable Read:开启事务后第一个select语句才是快照读的地方

如下:

MVCC有两个不同的隔离级别,生成的ReadView的实际不同

1.READ COMMITTED (读提交):在事务中每一次执行快照读时生成ReadView

2.REPEATABLE READ(可重复读): 仅在事务中第一次执行快照读时生成ReadView 后续复用该ReadView

  • 「读提交」隔离级别是在「每个select语句执行前」都会重新生成一个 Read View;
  • 「可重复读」隔离级别是执行第一条select时,生成一个 Read View,然后整个事务期间都在用这个 Read View。

就是在每次操作数据后,会将事务的由undolog进行保存,然后形成版本链表

对于使用 InnoDB 存储引擎的数据库表,它的聚簇索引记录中都包含下面两个隐藏列:

图片

  • trx_id,当一个事务对某条聚簇索引记录进行改动时,就会把该事务的事务 id 记录在 trx_id 隐藏列里
  • roll_pointer,每次对某条聚簇索引记录进行改动时,都会把旧版本的记录写入到 undo 日志中,然后这个隐藏列是个指针,指向每一个旧版本记录,于是就可以通过它找到修改前的记录。

Read View 有四个重要的字段:

trx_id表示的是当前MVCC读的事务id

img

  • m_ids :指的是在创建 Read View 时,当前数据库中「活跃事务」的事务 id 列表,注意是一个列表,“活跃事务”指的就是,启动了但还没提交的事务
  • min_trx_id :指的是在创建 Read View 时,当前数据库中「活跃事务」中事务 id 最小的事务,也就是 m_ids 的最小值。
  • max_trx_id :这个并不是 m_ids 的最大值,而是创建 Read View 时当前数据库中应该给下一个事务的 id 值,也就是全局事务中最大的事务 id 值 + 1;
  • creator_trx_id :指的是创建该 Read View 的事务的事务 id

在创建 Read View 后,我们可以将记录中的 trx_id 划分这三种情况:

一个事务去访问记录的时候,除了自己的更新记录总是可见之外,还有这几种情况:

  • 如果记录的 trx_id 值小于 Read View 中的 min_trx_id 值,表示这个版本的记录是在创建 Read View 已经提交的事务生成的,所以该版本的记录对当前事务可见

  • 如果记录的 trx_id 值大于等于 Read View 中的 max_trx_id 值,表示这个版本的记录是在创建 Read View 才启动的事务生成的,所以该版本的记录对当前事务不可见

  • 如果记录的 trx_id 值在 Read View 的 min_trx_id 和 max_trx_id 之间,需要判断 trx_id 是否在 m_ids 列表中:

  • 如果记录的 trx_id  m_ids 列表中,表示生成该版本记录的活跃事务依然活跃着(还没提交事务),所以该版本的记录对当前事务不可见

  • 如果记录的 trx_id 不在 m_ids列表中,表示生成该版本记录的活跃事务已经被提交,所以该版本的记录对当前事务可见

这种通过「版本链」来控制并发事务访问同一个记录时的行为就叫 MVCC(多版本并发控制)

例如在RC级别下

如图,当我们是事务5

可以访问的事务如下规则:

然后我们结合版本链

如图,我们的事务5可以的两条查询记录,可以根据他们的版本链来逐个分析,最后确定能够访问的版本,如第一个查询可以访问的是2,第二个是3

这样一来,当多个事务同时对表数据进行修改时,我们就可以知道哪个事务对应的修改的数据是哪个,同时也不会造成阻塞以及读写冲突问题

在RR级别下

由于仅在事务中第一次执行快照读时生成ReadView,后续复用该ReadView

所以每次的ReadView都是相同的

后面每次查询时使用的ReadView都是第一次的ReadView

相关文章:

  • 扩展摩尔投票法:找出出现次数超过 n/3 的元素
  • DAY 36神经网络加速器easy
  • 网络协议之办公室网络是怎样的?
  • 实验设计与分析(第6版,Montgomery)第3章单因子实验:方差分析3.11思考题3.7 R语言解题
  • 卸载 Office PLUS
  • ZYNQ-PS与PL端BRAM数据交互
  • PortSwigger-03-点击劫持
  • 链路追踪神器zipkin安装详细教程教程
  • Redis击穿,穿透和雪崩详解以及解决方案
  • Polar编译码(SCL译码)和LDPC编译码(BP译码)的matlab性能仿真,并对比香浓限
  • BEVDepth- Acquisition of Reliable Depth for Multi-view 3D Object Detection
  • 数据库管理与高可用-MySQL数据库操作
  • C# Datatable筛选过滤各方式详解
  • 智变与重构:AI 赋能基础教育教学的范式转型研究报告
  • jmeter对数据库进行单独压测
  • 黑马程序员C++核心编程笔记--3 函数高级
  • 【前端】【css预处理器】Sass与Less全面对比与构建对应知识体系
  • Visual Studio 的下载安装
  • 22.代理模式:思考与解读
  • Spring AI 代理模式(Agent Agentic Patterns)
  • 长春火车站停车场24小时收费标准/简单网页制作模板
  • 免费论坛网站建设/网络营销推广方案案例
  • 漳州 外贸网站建设 SEO/百度关键词广告怎么收费
  • 高端网站建设哪家更专业/徐州网站建设
  • 苏州360推广网站建设/线上宣传渠道
  • 沈丘做网站去哪里/提供seo顾问服务适合的对象是