【MySQL】MVCC及其实现原理

目录

1. 概念介绍

什么是MVCC

什么是当前读和快照读

MVCC的好处

2. MVCC实现原理

隐藏字段

Read View

undo-log

数据可见性算法

3. RC和RR隔离级别下MVCC的差异

4. MVCC+Next-key-Lock 防止幻读


1. 概念介绍

什么是MVCC

Multi-Version Concurrency Control 多版本并发控制,MVCC 是一种并发控制的方法,一般在数据库管理系统中,实现对数据库的并发访问;在编程语言中实现事务内存。

                                                                                                         MVCC_百度百科

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


什么是当前读和快照读

先来介绍一下MySQL下InnoDB索引的当前读和快照读:

  • 当前读(锁定读)

像 select lock in share mode (共享锁), select for update; update; insert; delete (排他锁)这些操作都是一种当前读,为什么叫当前读?就是它读取的是记录的最新版本,读取时还要保证其他并发事务不能修改当前记录,会对读取的记录进行加锁

  • 快照读(一致性非锁定读)

不加锁的 select 操作就是快照读,即不加锁的非阻塞读;快照读的前提是隔离级别不是串行级别,串行级别下的快照读会退化成当前读;之所以出现快照读的情况,是基于提高并发性能的考虑,快照读的实现是基于多版本并发控制,即 MVCC ,可以认为 MVCC 是行锁的一个变种,但它在很多情况下,避免了加锁操作,降低了开销;既然是基于多版本,即快照读可能读到的并不一定是数据的最新版本,而有可能是之前的历史版本

当前读是指读取数据时获取最新版本,并通过加锁确保其他事务无法修改该记录,以保证一致性。
快照读则是在不加锁的情况下读取数据,基于MVCC,可以访问历史版本,从而提高并发性能,但可能不获取最新数据。


MVCC的好处

  1. 提高并发性:通过允许多个事务同时访问不同版本的数据,减少了锁的竞争,从而提高了并发性能。

  2. 降低阻塞:读操作不需要等待写操作完成,减少了事务之间的阻塞,提升了响应速度。

  3. 保证一致性:每个事务都可以读取到一个一致的数据快照,避免了因并发更新导致的数据不一致问题。

  4. 性能优化:在许多情况下,MVCC可以避免加锁操作,降低了锁管理的开销,提升了数据库的整体性能。

  5. 灵活的事务处理:支持不同的隔离级别,可以根据需求灵活配置,以平衡性能和一致性。

2. MVCC实现原理

MVCC 的目的就是多版本并发控制,在数据库中的实现,就是为了解决读写冲突,它的实现原理主要是依赖记录中的 隐式字段undo日志 Read View 来实现的。所以我们先来看看它们的概念

隐藏字段

在内部,InnoDB 存储引擎为每行数据添加了三个 隐藏字段:

  • DB_TRX_ID(6字节):表示最后一次插入或更新该行的事务 id。此外,delete 操作在内部被视为更新,只不过会在记录头 Record header 中的 deleted_flag 字段将其标记为已删除
  • DB_ROLL_PTR(7字节) 回滚指针,指向该行的 undo log 。如果该行未被更新,则为空
  • DB_ROW_ID(6字节):如果没有设置主键且该表没有唯一非空索引时,InnoDB 会使用该 id 来生成聚簇索引

Read View

Read View 主要是用来做可见性判断,里面保存了 “当前对本事务不可见的其他活跃事务”:

主要有以下字段:

  • creator_trx_id:创建这个Read View的事务ID。这个ID标识了创建Read View的事务,而不是记录中的trx_id。如果是只读事务,事务ID默认为0。
  • m_ids:表示创建Read View时当前系统中活跃的读写事务的事务ID列表。这些是还未提交的事务,即启动了但还没提交的事务。

  • m_up_limit_id:表示创建Read View时活跃的事务中最小的事务ID。

  • m_low_limit_id:表示创建Read View时系统中应该分配给下一个事务的ID值,也就是当前最大事务ID+1。

class ReadView {/* ... */
private:trx_id_t m_low_limit_id;      /* 大于等于这个 ID 的事务均不可见 */trx_id_t m_up_limit_id;       /* 小于这个 ID 的事务均可见 */trx_id_t m_creator_trx_id;    /* 创建该 Read View 的事务ID */trx_id_t m_low_limit_no;      /* 事务 Number, 小于该 Number 的 Undo Logs 均可以被 Purge */ids_t m_ids;                  /* 创建 Read View 时的活跃事务列表 */m_closed;                     /* 标记 Read View 是否 close */
}

Read View 的作用主要是用来做可见性判断。当一个事务执行快照读操作时,它会使用Read View来判断自己能够看到哪个版本的数据。具体来说,系统会根据以下规则来判断记录的可见性:

不同的事务隔离级别下,Read View的生成时机也不同。例如,在READ COMMITTED隔离级别下,每次执行SELECT操作时都会生成一个新的Read View;而在REPEATABLE READ隔离级别下,只有在事务的第一次SELECT操作时会生成一个Read View,之后的查询都会复用这个Read View

  • 如果记录的trx_id等于creator_trx_id,说明这条记录是由当前事务自己修改的,因此对该事务是可见的。
  • 如果记录的trx_id小于m_up_limit_id,说明这个版本的记录是在创建Read View之前已经提交的事务生成的,所以该版本的记录对当前事务是可见的。
  • 如果记录的trx_id大于或等于m_low_limit_id,说明这个版本的记录是在创建Read View之后才启动的事务生成的,所以该版本的记录对当前事务是不可见的。
  • 如果记录的trx_id在m_up_limit_id和m_low_limit_id之间,就需要检查trx_id是否在m_ids列表中。如果在列表中,表示这个事务在Read View生成时刻还在活跃,还没有提交,因此该版本的记录对当前事务是不可见的;如果不在列表中,则说明这个事务在Read View生成之前就已经提交了,因此该版本的记录对当前事务是可见的。

事务可见性示意图


undo-log

undo log 主要有两个作用:

  • 当事务回滚时用于将数据恢复到修改前的样子
  • 另一个作用是 MVCC ,当读取记录时,若该记录被其他事务占用或当前版本对该事务不可见,则可以通过 undo log 读取之前的版本数据,以此实现非锁定读(快照读)

InnoDB 存储引擎中 undo log 分为两种:insert undo logupdate undo log

  1. insert undo log:指在 insert 操作中产生的 undo log。因为 insert 操作的记录只对事务本身可见,对其他事务不可见,故该 undo log 可以在事务提交后直接删除。不需要进行 purge 操作。insert 时的数据初始状态:
  2. update undo logupdatedelete 操作中产生的 undo log。该 undo log可能需要提供 MVCC 机制,因此不能在事务提交时就进行删除。提交时放入 undo log 链表,等待 purge线程 进行最后的删除

数据第一次被修改时:

数据第二次被修改时:

不同事务或者相同事务的对同一记录行的修改,会使该记录行的 undo log 成为一条链表,链首就是最新的记录,链尾就是最早的旧记录。


数据可见性算法

InnoDB 存储引擎中,创建一个新事务后,执行每个 select 语句前,都会创建一个快照(Read View),快照中保存了当前数据库系统中正处于活跃(没有 commit)的事务的 ID 号。其实简单的说保存的是系统中当前不应该被本事务看到的其他事务 ID 列表(即 m_ids)。当用户在这个事务中要读取某个记录行的时候,InnoDB 会将该记录行的 DB_TRX_IDRead View 中的一些变量及当前事务 ID 进行比较,判断是否满足可见性条件。

1. 如果记录 DB_TRX_ID<m_up_limit_id,那么表明最新修改该行的事务(DB_TRX ID)在当前事务创建快照之前就提交了,所以该记录行的值对当前事务是可见的
2. 如果 DB TRX ID >= m_low_limit_id,那么表明最新修改该行的事务(DB_TRX_ID)在当前事务创建2快照之后才修改该行,所以该记录行的值对当前事务不可见。跳到步骤5
3.m_ids 为空,则表明在当前事务创建快照之前,修改该行的事务就已经提交了,所以该记录行的值对当前事务是可见的
4. 如果 m_up_limit id <= DB TRX ID<m_low_limit_id,表明最新修改该行的事务(DB TRX ID)在4.当前事务创建快照的时候可能处于“活动态”或者“已提交状态”;所以就要对活跃事务列表 m iàs 进行查找(源码中是用的二分查找,因为是有序的)

  • 如果在活跃事务列表 m ids 中能找到 DB TRX ID,表明:① 在当前事务创建快照前,该记录行的值被事务 ID 为 DB TRX ID 的事务修改了,但没有提交;或者 ② 在当前事务创建快照后,该记录行的值被事务 ID 为 DB TRX ID 的事务修改了。这些情况下,这个记录行的值对当前事务都是不可见的。跳到步骤 5
  • 在活跃事务列表中找不到,则表明“id 为 trx_id 的事务”在修改“该记录行的值”后,在“当前事务”创建快照前就已经提交了,所以记录行对当前事务可见

5. 在该记录行的 DB_ROLL_PTR 指针所指向的 undo 1og取出快照记录,用快照记录的DB_TRX_ID 跳到步骤1重新开始判断,直到找到满足的快照版本或返回空。

3. RC和RR隔离级别下MVCC的差异

在MySQL的InnoDB存储引擎中,MVCC(多版本并发控制)是实现事务隔离级别的重要机制。MVCC通过保存数据的多个版本来允许读操作和写操作并发执行,从而提高数据库的并发性能。在RC(Read Committed)和RR(Repeatable Read)这两种隔离级别下,MVCC的工作方式有所不同。

RC隔离级别下的MVCC:

  • 在RC隔离级别下,每次执行快照读(SELECT)操作时,都会生成一个新的Read View。这意味着每次SELECT操作都可能看到不同的数据行版本,因为它们是基于各自时刻的Read View来判断数据的可见性。
  • Read View中包含了当前活跃的事务ID列表,以及这些事务的最小和最大事务ID。
  • 当读取一行数据时,会根据Read View来判断该数据行的版本是否对当前事务可见。

RR隔离级别下的MVCC:

  • 在RR隔离级别下,只有在事务的第一个快照读操作时会生成一个Read View,之后的快照读操作都会复用这个Read View。这样,同一个事务中多次执行SELECT操作,看到的都是事务开始时的数据行版本,从而保证了可重复读。
  • 这就意味着在RR隔离级别下,一个事务看不到其他事务在其第一个快照读之后对数据所做的修改。

4. MVCC+Next-key-Lock 防止幻读

InnoDB 存储引擎在 RR级别下通过 vcc和 Next-key Lock 来解决幻读问题。(在RC隔离级别下,由于每次SELECT操作都可能读取到最新的数据版本,因此不能避免幻读。)

1. 执行普通 select,此时会以 MVCC 快照读的方式读取数据

在快照读的情况下,RR 隔离级别只会在事务开启后的第一次查询生成 Read View ,并使用至事务提交。所以在生成 Read View 之后其它事务所做的更新、插入记录版本对当前事务并不可见,实现了可重复读和防止快照读下的 “幻读”

2、执行 select...for update/lock in share mode、insert、update、delete 等当前读

在当前读下,读取的都是最新的数据,如果其它事务有插入新的记录,并且刚好在当前事务查询范围内,就会产生幻读!InnoDB 使用 Next-key Lock 来防止这种情况。当执行当前读时,会锁定读取到的记录的同时,锁定它们的间隙,防止其它事务在查询范围内插入数据。只要我不让你插入,就不会发生幻读

这种锁定机制(Next-Key Lock)有效地解决了幻读问题,幻读是指事务在前后两次查询同一个范围的时候,第二次查询看到了第一次查询没有看到的行。由于Next-Key Lock的存在,当事务A在读取某个范围内的记录时,事务B想要在这个范围内插入一条新的记录将会被阻塞,直到事务A释放了锁。这样,事务A再次查询时,就不会看到那些原本不存在的“幻读”行.

参考


  • 《MySQL 技术内幕 InnoDB 存储引擎第 2 版》
  • Innodb 中的事务隔离级别和锁的关系
  • MySQL 事务与 MVCC 如何实现的隔离级别
  • InnoDB 事务分析-MVCC
  • InnoDB存储引擎对MVCC的实现 | JavaGuide

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1547434.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

FGPA实验——触摸按键

本文系列都基于正点原子新起点开发板 FPGA系列 1&#xff0c;verlog基本语法&#xff08;随时更新&#xff09; 2&#xff0c;流水灯&#xff08;待定&#xff09; 3&#xff0c;FGPA实验——触摸按键 一、触摸操作原理实现 分类&#xff1a;电阻式&#xff08;不耐用&…

LeetCode - 850 矩形面积 II

题目来源 850. 矩形面积 II - 力扣&#xff08;LeetCode&#xff09; 题目描述 给你一个轴对齐的二维数组 rectangles 。 对于 rectangle[i] [x1, y1, x2, y2]&#xff0c;其中&#xff08;x1&#xff0c;y1&#xff09;是矩形 i 左下角的坐标&#xff0c; (xi1, yi1) 是该…

通信工程学习:什么是VIM虚拟化基础设施管理器

VIM:虚拟化基础设施管理器 VIM(Virtualized Infrastructure Manager)虚拟化基础设施管理器,是一种负责管理和控制虚拟化环境中所有虚拟资源的工具和系统。以下是关于VIM虚拟化基础设施管理器的详细解释: 一、定义与功能 VIM是网络功能虚拟化(NFV)架构中…

李宏毅机器学习2023-HW10-Adversarial Attack

文章目录 TaskBaselineFGSM (Fast Gradient Sign Method (FGSM)I-FGSM(Iterative Fast Gradient Sign Method)MI-FGSM(Momentum Iterative Fast Gradient Sign Method)M-DI2-FGSM(Diverse Input Momentum Iterative Fast Gradient Sign Method) Reportfgsm attackJepg Compress…

探索5 大 Node.js 功能

目录 单线程 Node.js 工作线程【Worker Threads】 Node.js 进程 进程缺点 工作线程 注意 集群进程模块【Cluster Process Module】 内部发生了什么&#xff1f; 为什么要使用集群 注意&#xff1a; 应用场景&#xff1a; 内置 HTTP/2 支持 这个 HTTP/2 是什么&…

Windows安装Vim,并在PowerShell中直接使用vim

大家好啊&#xff0c;我是豆小匠。 这期介绍下怎么在windows的PowerShell上使用vim&#xff0c;方便在命令行里修改配置文件等。 先上效果图&#xff1a; 1、下载Vim GitHub传送门&#xff1a;https://github.com/vim/vim-win32-installer/releases 选择win-64的版本下载即可&…

VS Code使用Git Bash终端

Git Bash可以运行linux命令&#xff0c;在VS Code的终端界面&#xff0c;找到号旁边的箭头&#xff0c;就能直接切换了 当然&#xff0c;前提是安装了Git Bash&#xff0c;并且在资源管理器里&#xff0c;能鼠标右键出"Git Bash Here"

node.js从入门到快速开发一个简易的web服务器

浏览器中JavaScript学习路径: JavaScript基础语法浏览器内置API(DOMBOM)第三方库(jQuery,art-template等) Node.js的学习路径 JavaScript基础语法Node.js内置API模块(fs、path、http等)第三方API模块(express、mysql等) Node.js安装 通过Node.js 来运行Javascript 代码&am…

[已解决]npm install报错

问题分析&#xff1a; 想执行文件夹下的npm install&#xff0c;通过以及cmd进入&#xff0c;都会报错权限不够 如下报错&#xff08;哪一张不清楚&#xff0c;只知道是权限不够导致的&#xff09; 问题解决&#xff1a; 搜索Windows powershell 然后用管理员权限启动&#x…

【C++篇】深度剖析C++ STL:玩转 list 容器,解锁高效编程的秘密武器

文章目录 C list 容器详解&#xff1a;从入门到精通前言第一章&#xff1a;C list 容器简介1.1 C STL 容器概述1.2 list 的特点 第二章&#xff1a;list 的构造方法2.1 常见构造函数2.1.1 示例&#xff1a;不同构造方法2.1.2 相关文档 第三章&#xff1a;list 迭代器的使用3.1 …

基于skopt的贝叶斯优化基础实例学习实践

贝叶斯方法是非常基础且重要的方法&#xff0c;在前文中断断续续也有所介绍&#xff0c;感兴趣的话可以自行移步阅读即可&#xff1a; 《数学之美番外篇&#xff1a;平凡而又神奇的贝叶斯方法》 《贝叶斯深度学习——基于PyMC3的变分推理》 《模型优化调参利器贝叶斯优化bay…

使用API有效率地管理Dynadot域名,设置域名服务器(NS)

前言 Dynadot是通过ICANN认证的域名注册商&#xff0c;自2002年成立以来&#xff0c;服务于全球108个国家和地区的客户&#xff0c;为数以万计的客户提供简洁&#xff0c;优惠&#xff0c;安全的域名注册以及管理服务。 Dynadot平台操作教程索引&#xff08;包括域名邮箱&…

Type-C接口相关知识:【总结大全】

Type-c现在非常通用了&#xff0c;所以了解Type-c也变得十分有必要了&#xff0c;还是秉承了解就要了解清楚的原则&#xff0c;我们深入的看看Type-c接口。 Type-c主要是取代上一代Micro usb接口&#xff0c;那么Type-c有什么优点呢&#xff1f; 正反可插&#xff0c;使用时不…

电脑usb接口封禁如何实现?5种禁用USB接口的方法分享!(第一种你GET了吗?)

“防患于未然&#xff0c;安全始于细节。”在信息技术飞速发展的今天&#xff0c;企业的信息安全问题日益凸显。 USB接口作为数据传输的重要通道&#xff0c;在带来便利的同时&#xff0c;也成为了数据泄露和安全风险的高发地。 因此&#xff0c;对电脑USB接口进行封闭管理&a…

植物大战僵尸杂交版V2.5.1下载(最新版)

2.5.1版本更新公告&#xff1a; 在最新的2.5.1版本中&#xff0c;游戏对“两面夹击”关卡进行了多项重要调整。出怪倍率和种类均有所降低&#xff0c;部分关卡的初始阳光量也得到了调整&#xff0c;以增强玩家的策略性。同时&#xff0c;玩家可以在这些关卡中使用投手类植物&a…

视频集成与融合项目中需要视频编码,但是分辨率不兼容怎么办?

在众多视频整合项目中&#xff0c;一个显著的趋势是融合多元化的视频资源&#xff0c;以实现统一监管与灵活调度。这一需求促使项目团队不断探索新的集成方案&#xff0c;确保不同来源的视频流能够无缝对接&#xff0c;共同服务于统一的调看与管理平台&#xff0c;进而提升整体…

基于SSM+小程序的英语学习交流平台管理系统(学习3)(源码+sql脚本+视频导入教程+文档)

&#x1f449;文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1 、功能描述 本英语学习交流平台小程序有管理员和用户两个角色。 1、管理员功能有&#xff0c;个人中心&#xff0c;用户管理&#xff0c;每日打卡管理&#xff0c;备忘录管理&#xff0c;学习计划管…

【传感器技术】【第1章 传感器与检测技术的理论基础,测量系统,测量分类,误差分析,估计和处理】

目录 第1章 传感器与检测技术的理论基础 1.1 测量系统 2&#xff0e;开环测量系统与闭环测量系统 3、 测量概念 1.2 测量分类 1&#xff0e; 直接测量、 间接测量与组合测量 2&#xff0e; 等精度测量与不等精度测量 3&#xff0e; 偏差式测量、 零位式测量与微差式测量…

相机、镜头参数详解以及相关计算公式

一、工业相机参数 1、分辨率 相机每次采集图像的像素点数&#xff0c;也是指这个相机总共有多少个感光晶片。在采集图像时&#xff0c;相机的分辨率对检测精度有很大的影响&#xff0c;在对同样打的视场成像时&#xff0c;分辨率越高&#xff0c;对细节的展示越明显。 相机像素…

微信小程序配置prettier+eslint

虽然微信开发者工具是基于vscode魔改的.但是由于版本过低,导致很多插件也用不上新版本.所以在微信开发者工具限制的版本下使用的prettier,eslint也是有版本要求. 本文主要就是记录一下需要的版本号 1.微信开发者工具安装插件 2.package.json中添加以下依赖及安装依赖 "de…