MySQL(四)多版本并发控制 ----- MVCC

3、MVCC多版本并发控制 事务2在快照读该行记录的时候,就会拿该行记录的DB_TRX_ID去跟min_id,next_trx_id和活跃事务ID列表(trx_list)进行比较,判断当前事务2能看到该记录的版本是哪个。Read View就是事务进行快照读操作的时候生产的读视图(Read View),在该事务执行的快照读的那一刻,会生成数据库系统当前的一个快照,记录并维护系统当前活跃事务的ID(当每个事务开启时,都会被分配一个ID, 这个ID是递增的,所以最新的事务,ID值越大)而当前读就是悲观锁的具体功能实现。 阅读详情

前言

InnoDB 存储引擎在事务隔离级别 READ COMMITTED 和 REPEATABLE READ(默认)下会开启一致性非锁定读,简单回顾下:所谓一致性非锁定读就是每行记录可能存在多个历史版本,多版本之间串联起来形成了一条版本链,这样不同时刻启动的事务可以无锁地访问到不同版本的数据。

undo log 版本链

一致性非锁定读是通过 MVCC(Multi Version Concurrency Control,多版本并发控制) 来实现的。事实上,MVCC 没有一个统一的实现标准,所以各个存储引擎的实现机制不尽相同。

InnoDB 存储引擎中 MVCC 的实现是通过 undo log 来完成的,undo log 是啥?

简单理解,undo log 就是每次操作的反向操作,比如比如当前事务执行了一个插入 id = 100 的记录的操作,那么 undo log 中存储的就是删除 id = 100 的记录的操作。

所以,这里用多版本来形容并不是非常准确,因为 InnoDB 并不会真正地去开辟空间存储多个版本的行记录,只是借助 undo log 记录每次写操作的反向操作。

也就是说,B+ 索引树上对应的记录只会有一个最新版本,只不过 InnoDB 可以根据 undo log 得到数据的历史版本,从而实现多版本控制。

在这里插入图片描述

那么,还有个问题,undo log 是如何和某条行记录产生联系的呢?换句话说,我怎么能通过这条行记录找到它拥有的 undo log 呢?

具体来说,InnoDB 存储引擎中每条行记录其实都拥有两个隐藏的字段:trx_id 和 roll_pointer。

从名字也能看出来,trx_id 就是最近更新这条行记录的事务 ID,roll_pointer 就是指向之前生成的 undo log。

掏出我们的 user 表,来举个例子,假设 id = 100 的事务 A 插入一条行记录(id = 1, username = “Jack”, age = 18),那么,这行记录的两个隐藏字段 trx_id = 100 和 roll_pointer 指向一个空的 undo log,因为在这之前并没有事务操作 id = 1 的这行记录。如图所示:

在这里插入图片描述

然后,id = 200 的事务 B 修改了这条行记录,把 age 从 18 修改成了 20,于是,这条行记录的 trx_id 就变成了 200,rooll_pointer 就指向事务 A 生成的 undo log :

在这里插入图片描述
接着,id = 300 的事务 C 再次修改了这条行记录,把 age 从 20 修改成了 30,如下图:

在这里插入图片描述
可以看到,每次修改行记录都会更新 trx_id 和 roll_pointer 这两个隐藏字段,之前的多个数据快照对应的 undo log 会通过 roll_pointer 指针串联起来,从而形成一个版本链。

需要注意的是,select 查询操作不会生成 undo log!在 InnoDB 存储引擎中,undo log 只分为两种:

  • insert undo log:在 insert 操作中产生的 undo log
  • update undo log:对 delete 和 update 操作产生的 undo log

事实上,由于事务隔离性的要求,insert 操作的记录,只对事务本身可见,对其他事务不可见,对吧,所以也就不存在并发情况下的问题。所以,也就是说,MVCC 这个机制,其实就是靠 update undo log 实现的,和 insert undo log 基本上没啥关系,我们上面说的 undo log 版本链上的其实就是 update undo log。

ReadView 机制

ReadView 机制就是用来判断当前事务能够看见哪些版本的,一个 ReadView 主要包含如下几个部分:

  • m_ids:生成 ReadView 时有哪些事务在执行但是还没提交的(称为 ”活跃事务“),这些活跃事务的 id 就存在这个字段里
  • min_trx_id:m_ids 里最小的值
  • max_trx_id:生成 ReadView 时 InnoDB 将分配给下一个事务的 ID 的值(事务 ID 是递增分配的,越后面申请的事务 ID 越大)
  • creator_trx_id:当前创建 ReadView 事务的 ID

接下来,再掏出 user 表,通过一个例子来理解下 ReaView 机制是如何做到判断当前事务能够看见哪些版本的:

假设表中已经被之前的事务 A(id = 100)插入了一条行记录(id = 1, username = “Jack”, age = 18),如图所示:

在这里插入图片描述
接下来,有两个事务 B(id = 200) 和 C(id = 300)过来并发执行,事务 B 想要更新(update)这行 id = 1 的记录,而事务 C(select)想要查询这行数据,这两个事务都执行了相应的操作但是还没有进行提交:

在这里插入图片描述
如果现在事务 B 开启了一个 ReadView,在这个 ReadView 里面:

  • m_ids 就包含了当前的活跃事务的 id,即事务 B 和事务 C 这两个 id,200 和 300
  • min_trx_id 就是 200
  • max_trx_id 是下一个能够分配的事务的 id,那就是 301
  • creator_trx_id 是当前创建 ReadView 事务 B 的 id 200

在这里插入图片描述
现在事务 B 进行第一次查询(上面说过 select 操作不会生成 undo log 的哈),会把这行记录的隐藏字段 trx_id 和 ReadView 的 min_trx_id 进行下判断,此时,发现 trx_id 是 100,小于 ReadView 里的 min_trx_id(200),这说明在事务 B 开始之前,修改这行记录的事务 A 已经提交了,所以开始于事务 A 提交之后的事务 B、是可以查到事务 A 对这行记录的更新的。

在这里插入图片描述
接着事务 C 过来修改这行记录,把 age = 18 改成了 age = 20,所以这行记录的 trx_id 就变成了 300,同时 roll_pointer 指向了事务 C 修改之前生成的 undo log

在这里插入图片描述
那这个时候事务 B 再次进行查询操作,会发现这行记录的 trx_id(300)大于 ReadView 的 min_trx_id(200),并且小于 max_trx_id(301)。

这说明一个问题,就是更新这行记录的事务很有可能也存在于 ReadView 的 m_ids(活跃事务)中。所以事务 B 会去判断下 ReadView 的 m_ids 里面是否存在 trx_id = 300 的事务,显然是存在的,这就表示这个 id = 300 的事务是跟自己(事务 B)在同一时间段并发执行的事务,也就说明这行 age = 20 的记录事务 B 是不能查询到的。

在这里插入图片描述
既然无法查询,那该咋整?事务 B 这次的查询操作能够查到啥呢?

没错,undo log 版本链!

这时事务 B 就会顺着这行记录的 roll_pointer 指针往下找,就会找到最近的一条 trx_id = 100 的 undo log,而自己的 id 是 200,即说明这个 trx_id = 100 的 undo log 版本必然是在事务 B 开启之前就已经提交的了。所以事务 B 的这次查询操作读到的就是这个版本的数据即 age = 18。

通过上述的例子,我们得出的结论是,通过 undo log 版本链和 ReadView 机制,可以保证一个事务不会读到并发执行的另一个事务的更新。

那自己修改的值,自己能不能读到呢?

这当然是废话,肯定可以读到呀。不过上面的例子我们只涉及到了 ReadView 中的前三个字段,而 creator_trx_id 就与自己读自己的修改有关,所以这里还是图解出来让大家更进一步理解下 ReadView 机制:

假设事务 C 的修改已经提交了,然后事务 B 更新了这行记录,把 age = 20 改成了 age = 66,如下图所示:

在这里插入图片描述
然后,事务 B 再来查询这条记录,发现 trx_id = 200 与 ReadView 里的 creator_trx_id = 200 一样,这就说明这是我自己刚刚修改的啊,当然可以被查询到。

在这里插入图片描述
那如果在事务 B 的执行期间,突然开了一个 id = 400 的事务 D,然后更新了这行记录的 age = 88 并且还提交了,然后事务 B 再去读这行记录,能读到吗?

在这里插入图片描述
答案是不能的。

因为这个时候事务 B 再去查询这行记录,就会发现 trx_id = 500 大于 ReadView 中的 max_trx_id = 301,这说明事务 B 执行期间,有另外一个事务更新了数据,所以不能查询到另外一个事务的更新。

在这里插入图片描述
那通过上述的例子,我们得出的结论是,通过 undo log 版本链和 ReadView 机制,可以保证一个事务只可以读到该事务自己修改的数据或该事务开始之前的数据。

小结

总结下,通过 undo log 版本链和 ReadView 机制:

  • 可以保证一个事务不会读到并发执行的另一个事务的更新
  • 可以保证一个事务只可以读到该事务自己修改的数据或该事务开始之前的数据

另外,前文说过,一致性非锁定读(或者直接说 MVCC 吧,毕竟一致性非锁定读也是靠 MVCC 实现的)只在事务隔离级别 READ COMMITTED 和 REPEATABLE READ(默认)下才会开启,那对于这两个隔离级别,其实最根本的不同之处,就在于它们生成 ReadView 的时机不同。

MVCC多版本并发控制 MVCC(多版本并发控制)是数据库解决读写冲突的无锁机制,通过维护数据多个版本实现非阻塞读写。其核心原理包括三个隐式字段(事务ID、回滚指针、行ID)、undo日志版本链和ReadView可见性判断。MVCC通过快照读(读取历史版本)和当前读(加锁读取最新版本)的区分,有效解决了脏读、不可重复读等问题,同时提升并发性能。不同隔离级别下MVCC实现存在差异:RR级别同一事务内使用相同ReadView保证可重复读,RC级别每次快照读生成新ReadView可看到已提交事务的修改。MVCC通过版本链管理和可见性算法 阅读详情

相关推荐

机器学习——径向基函数(RBF)神经网络

目录 一、什么是基函数 二、什么是径向基函数 三、为什么RBF神经网络使用一个径向基函数作为隐含层的激活函数 四、参数训练 五、RBF网络vs BP网络和 SVM 一、什么是基函数 著名的傅里叶变换是指:n个有参(权值)的正、余弦三角函数基的和式可以等价的表示任意一个周期函数,这里的“基”和我们数学中说的坐标基或向量基含义相同,即坐标空间中任意一个向量都可以用基向量的线性和表示出来。 因此,我们引入函数空间的概念,函数空间中的每个连续函数可以表示为基函数的线性组合,就像向量空间中的每..

CHWB2580的博客 6271

MYSQL隔离级别和MVCC

MYSQL隔离级别和MVCC

m0_47637225的博客 761

Moveit +Gazebo:搭建单臂机械臂仿真平台

Moveit +Gazebo:搭建单臂机械臂仿真平台

magic_invaid的博客 5287

三分钟图解 MVCC,看一遍就懂

所谓一致性非锁定读就是每行记录可能存在多个历史版本,多版本之间串联起来形成了一条版本链,这样不同时刻启动的事务可以无锁地访问到不同版本的数据。 undo log 版本链 一致性非锁定读是通过MVCC(Multi Version Concurrency Control,多版本并发控制)来实现的。事实上,MVCC 没有一个统一的实现标准,所以各个存储引擎的实现机制不尽相同。 InnoDB 存储引擎中 MVCC 的实现是通过undo log来完成的,undo log 是啥? 简单理解,undo l...

qq_46388795的博客 506

ENVI+SARscape实战:从哨兵一号数据到地震形变制图全流程解析

本文详细解析了使用ENVI和SARscape软件从哨兵一号数据生成地震形变图的全流程,包括数据获取、干涉处理、相位解缠等关键步骤。通过实战技巧和参数设置建议,帮助用户高效处理SAR数据,提升地震形变监测的精度和可视化效果。

weixin_30460489的博客 385

大模型部署指南:SGLang 框架

本文介绍使用 SGLang 框架部署大模型

举世誉之而不加劝,举世非之而不加沮,定乎内外之分,辩乎荣辱之境,斯已矣。 1611

深入理解mysql中的MVCC

深入理解mysql中的MVCC 一. 概念 先简单介绍一些概念,如果你已经知道了可以快速跳过该部分内容 MVCC:Multi-Version Concurency Control,即多版本并发控制,它能够更好的帮助数据组提升并发读写能力 隔离级别:mysql提供四种隔离级别,分别是READ UNCOMMITTED,READ COMMITTED,REPEATABLE READ,SERIALIZABLE,默认的是REPEATABLE READ mysql不同的隔离级别可能遇到不一样的问题,如,脏读

hongtaolong的博客 436

【ComfyUI专栏】安装Triton组件

Triton是一款支持大模型推理的深度学习加速组件,最初仅支持Linux平台,现已通过开源社区适配Windows系统。针对SageAttention的安装,建议使用3.2.0Post10版本(该版本提供封装好的安装包,更高版本仅有源码)。用户可通过GitHub获取安装资源,或直接使用pip命令"pip install triton-windows"进行安装。安装时需注意:1)在虚拟环境中操作;2)使用管理员权限。相关资源链接已在文中提供。

技术与管理的平衡木- 1858

mysql的mvcc和readview

mvcc和readview

m0_60684005的博客 461

基于STM32L4XX的环境光传感器(AS7343-DLGMN)应用程序设计

define AS7343_STATUS_SPECTRAL_INT (1 << 3) /* 光谱数据就绪 */#define AS7343_SYS_CFG_SPECTRAL_EN (1 << 1) /* 光谱测量使能 */#define AS7343_SYS_CFG_ALS_EN (1 << 0) /* ALS使能 */#define AS7343_SYS_CFG_INT_EN (1 << 4) /* 中断使能 *//* 切换通道组 (0=组1 F1-F6, 1=组2 F7-F12) */

myron6688的博客 257

【基于 CasADi 的欠驱动无人船实时非线性模型预测控制(NMPC)实现 Visual Studio 2022 C++】

本文介绍了基于CasADi和IPOPT在Visual Studio 2022 C++环境下实现的欠驱动无人船实时非线性模型预测控制(NMPC)方案。文章详细阐述了NMPC基本原理、欠驱动无人船动力学模型(包含状态变量和控制变量定义),并给出了C++实现的核心代码框架。该方案通过显式引入系统动力学模型和约束条件,在每个采样周期滚动优化控制序列,有效解决了欠驱动无人船的轨迹跟踪与避碰问题。文中还提供了VS2022配置CasADi环境的详细步骤,包括预编译包下载、工程属性设置等关键环节,为工程实现提供了完整的技术

vor234的博客 650

MVCC 初识

qq_39368007的博客 219

华为面试手撕真题【最长不重复子串】

给定一个字符串s,请你找出其中不含有重复字符的最长子串的长度。

MISAYAONE的博客 1万+

大话Mysql四:Mysql事务之MVCC多版本并发控制

一、Mysql mvcc 就是在一个事务开启之前对其数据进行快照备份,通过读取快照的方式来确保同一个事务前后读取到的数据是相同的,这就叫多版本的并发控制 MVCC 多版本并发控制规则: 1、一个事务能看到的数据版本: (1)、第一个查询之前已经提交的事务 (2)、本事务的修改 2、一个事务无法看到的版本: (1)、第一个查询之后创建的事务(事务ID相较于当前事务Id要大的事务) (2)、活跃(未提交)的事务的修改 二、MVCC 原理 Innodb引擎为每行记录都实现了两个隐藏字段: DB_TRX_ID 和

lyzchengxuyuan的博客 555

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

MySQL 专题(四):MVCC(多版本并发控制)原理深度解析

MVCC 的核心快照读依赖 MVCC,可以高并发下无锁读取。可重复读(RR)的实现依赖固定的 ReadView。幻读问题仍需间隙锁来解决。MVCC 让 MySQL 在“读多写少”的场景中,既能保证一致性,又能兼顾高性能,是 InnoDB 的灵魂设计之一。

波波烤鸭的博客 1069

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

高性能 MySQL(四):多版本并发控制(MVCC)

MVCC(Multiversion Concurrency Control)即多版本并发控制,它是数据库系统常用的一种并发控制,用于提升事务内数据的并发性。可以认为 MVCC 是行锁的一个变种,在很多种情况下避免了加锁操作,因此开销更低。

水滴的博客 870

MySQL梳理四:事务日志机制和多版本并发控制(MVCC)

深入剖析redo log和undo log如何协同保障ACID特性,详细解释四种事务隔离级别的工作原理和性能权衡,通过WAL预写日志策略和MVCC版本管理机制,展示MySQL如何在保障数据一致性的同时实现高并发性能

Bai168779的博客 610

MVCC多版本并发控制: 可重复读隔离级别如何通过ReadView解决幻读?

概念 | 说明 | RR行为 | RC行为 || ReadView创建 | 快照读时创建 | 第一次创建,后续复用 | 每次创建新的 || 可见性规则 | trx_id与m_ids比较 | 严格按规则 | 每次刷新快照 || 快照读幻读 | 普通SELECT | 不会 | 可能 || 当前读幻读 | FOR UPDATE | 间隙锁阻止 | 可能 || 例外场景 | UPDATE后SELECT | 可能看到新数据 | - |

✨ 欢迎来到【Seal ^_^ 的优快云博客】!✨ 1475

Mysql中的MVCC(多版本并发控制)

目录1、MySQL的逻辑架构1.1、redo log日志1.2、binlog 日志1.3、redo log和binlog区别1.4、undo log(回滚日志)2、MVCC是啥2.1、什么是当前读和快照读?2.1、MVCC作用3、MVCC的实现原理3.1、隐式字段3.2、行的更新过程3.3、Read View(读视图)3.4、MVCC 整体流程RC,RR级别下的InnoDB快照读有什么不同?附录 1、MySQL的逻辑架构 1.1、redo log日志 redo log(重做日志):redo log是Inn

weixin_42412601的博客 5405

mysql中MVCC多版本并发控制原理的详解

今天我们分享mysql中MVCC多版本并发控制原理的详解 一、MVCC定义 1、MVCC简介 MVCC,全称Multi-Version Concurrency Control,即多版本井发控制,MVCC是一种并发控制的方法,一般在数据库管理系统中,实现对数据库的并发访问,在编程语言中实现事务内存。 MVCC在MysQL InnoDB中的实现主要是为了提高数据库并发性能,用更好的方式去处理读写冲突。做到即使有读写冲突时,也能做到不加锁,非阻塞并发读。 2、当前读 像select lock in sha.

nandao158的博客 1万+

【MySQL】解析MVCC多版本并发控制

MVCC(Multiversion Concurrency Control),多版本并发控制。顾名思义,MVCC是通过数据行的多个版本管理来实现数据库的并发控制。这项技术使得在InnoDB的事务隔离级别下执行一致性读操作有了保证。换言之,就是为了查询一些正在被另一事务更新的行,并且可以看到它们被更新之前的值,这样在做查询的时候就不同等待另一个事务释放锁。MVCC没有正式的标准,在不同的DBMS中MVCC的实现方式可能是不同的,也不是普遍使用的。

smile_sundays的博客 1269

【MySQL基础】MVCC多版本并发控制

MVCC多版本并发控制

scj1022的博客 2732

MySQL-多版本并发控制MVCC

快照内容读取原则:1、当前事务未提交无法读取生成快照2、事务已提交,但是在快照创建后提交的,无法读取;3、事务已提交,但是在快照创建前提交的,可以读取;4、当前事务内自己的更新,可以读到;所以在可重复读隔离级别下会产生幻读。

qq_45855355的博客 1756

MySQL 多版本并发控制 MVCC

MySQL 多版本并发控制 MVCC

lolly1023的博客 1580

一篇详解MVCC多版本并发控制的原理

MVCC(Multi-Version Concurrency Control),即多版本并发控制,在MySQL InnoDB中处理并发时,不加锁和非阻塞并发读,提高并发读性能的一种机制。MVCC维持了数据的多个版本,使得并发读写时没有冲突。

weixin_56602545的博客 9178

MySQL:简述多版本并发控制MVCC

Read View遵循的可见性算法主要是将要被修改的数据的最新记录中的DB_TRX_ID(当前事务id)取出来,与系统当前其他活跃事务的id去对比,如果DB_TRX_ID跟Read View的属性做了比较,不符合可见性,那么就通过DB_ROLL_PTR回滚指针去取出undolog中的DB_TRX_ID做比较,即遍历链表中的DB_TRX_ID,直到找到满足条件的DB_TRX_ID,这个DB_TRX_ID所在的旧记录就是当前事务能看到的最新老版本数据。(1)在事务3修改该行数据的时,数据库会对该行加排他锁。

王小二(海阔天空) 1470
上一篇: MySQL(三)锁 ----- 行锁和锁机制
下一篇: MySQL(五)一致性非锁定读与一致性锁定读
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值