MySQL多版本并发控制MVCC实现原理
MVCC
MVCC 是多版本并发控制方法,用来解决读和写之间的冲突,比如脏读、不可重复读问题,MVCC主要针对读操作做限制,保证每次读取到的数据都是本次读取之前的已经提交事务所修改的。
概述
当一个事务要对数据库中的数据进行select查找时,MVCC 会为该事务创建一个read view数据快照,查询语句会把在read view产生之前没提交的修改以及在read view产生之后才提交的事务对应的修改屏蔽掉,最终只能读取到这个read view产生之前其它事务所提交的更改。换句话说,读操作读取的是旧版本数据(也可能是最新的),而写操作是针对最新的版本记录,所以能解决读-写冲突问题。
具体实现
它基于数据行的隐藏字段、undo log版本链、read view实现:
数据隐藏字段:最后修改事务id、回滚记录指针

undo log 版本链:用于记录某行数据的多个版本的数据,通过一个回滚指针字段链接起来

read view : 每个事务的读取时会产生一个read view,记录了一些列的事务id,具体有如下四个字段:
- creator_trx_id,创建当前Read View的事务ID。
- trx_ids,表示在生成ReadView时当前系统中活跃的读写事务的事务id列表。
- min_limit_trx_id,活跃的事务中最小的事务id。
- max_trx_id,表示生成ReadView时系统中应该分配给下一个事务的id值。low_limit_id是系统最大的事务id值,这里要注意是系统中的所有事务id,不仅包含正在活跃的事务id、还包含之前已提交的事务id。
注意:
- 只有在对表中的记录做改动时(执行INSERT、DELETE、UPDATE这些语句时)才会为事务分配事务id,否则在一个只读事务中的事务id值都默认为0。
- low_limit_id并不是活跃事务列表trx_ids中的最大值,而是所有事务id中最大的+1,这里的所有事务包括活跃的、已提交的。比如,现在有id为1,2,3这三个事务,之后id为3的事务提交了。那么一个新的读事务在生成ReadView时,trx_ids就包括1和2,up_limit_id的值就是1,low_limit_id的值就是4。
MVCC工作流程
- 某个事务执行select查找时,首先根据数据行的某个字段获取事务自己的版本号,也就是事务ID;
- 然后创建ReadView;
- 查询得到最新数据,然后与ReadView中的事务版本号按照一定规则进行比较;
- 如果不符合ReadView规则,就需要从Undo Log 中获取历史快照;
- 一直往前查找,直到返回符合规则的数据。
read view是怎么去找到当前read view创建之前已经提交修改的最新数据的,具体规则是什么?
先根据数据行记录的回滚指针,在undo日志中找到最新一条记录,找到其对应的事务id,然后做四轮对比:
- 对比最新记录的事务id和当前read view的事务id,如果相同,则说明最新的数据就是当前事务修改的,可以直接读。(等于当前id,代表是自己改的,则可读)
- 对比最新记录的事务id和当前read view的记录的活跃事务id最小值,看看是不是当前记录是不是read view创建之前就已经提交完的,如果是,则可以直接读。(小于最小活跃事务id,代表之前提交的修改,则可读)
- 对比最新记录的事务id和当前read view的记录的最大事务id,看看当前记录是不是read view创建之后才有的,如果是就不读。(大于最大事务id,代表后面才提交的修改,不可读)
- 对比最新记录的事务id是不是存在于当前活跃事务id列表当中,如果存在,则说明是未提交的数据,不能读取;如果不存在,则可读。(在活跃事务列表里,代表未提交的修改,可读)
这四轮对比完之后,如果都显示不能读,则找到undo日志的下一跳数据,继续四轮对比。知道找到某条可读的记录。
假设事务5创建read view时,系统中有8个事务,对应查找情况如下:

疑问:其实整个流程就是把那些活跃事务(未提交)造成的修改排除掉,然后再判断下当前事务是创建read view之前提交的还是创建read view之后提交的,那为什么要在最后一步才去判断事务id是否在活跃id列表中?
自我理解:因为判断某个id是否在活跃事务id列表里,需要一次遍历操作,放在第一步去做的话每次都要遍历,速度很慢;其实可以先把其它情况处理掉(不需要遍历),当别的情况都不满足时,最后再考虑是否在活跃id列表中,以此提高查找效率。
事务隔离级别与MVCC
四个事务隔离级别与MVCC的关系?
首先,最低的读未提交和串行化没有用到MVCC机制,而读已提交和可重复度用到了MVCC去解决读写冲突中的脏读取和不可重复读的问题。
读已提交隔离级别中,MVCC怎么解决脏读的?
同一个事务中每次读取时创建一个read view,根据read view中记录的事务id去undo log中把其它未提交事务的记录个过滤掉,只会读取已提交事务所造成的修改。
问题:因为每次查询都会创建一个read view,所以两次查询之间,如果其它事务对数据进行修改,这时对第二次查询产生的read view的视角下,刚刚的修改是可见的,所以这就有了不可重复读的问题。

可重复读隔离级别中,MVCC怎么解决不可重复读?保证可重复读?
对于同一个事务中对同一条数据的多次读取,复用之前的read view,也就是只有在首次读取数据时才会产生read view,这就避免了出现在一个事务中的多次读取结果不一样的情况。

总结MVCC机制
MVCC 是多版本并发控制方法,用来解决读和写之间的冲突,比如脏读、不可重复读问题,MVCC主要针对读操作做限制,保证每次读取到的数据都是本次读取之前的已经提交事务所修改的。
它具体实现依赖于数据行隐藏字段、undo log版本链和read view。
具体过程:在某个事务执行读操作时,可以通过数据行的隐藏列去找到undo日志中的历史版本记录,每个历史版本记录里面都记录了事务id,然后会读操作会创建一个read view视图,里面包含了一些事务id的数据,然后通过对比read view里面的事务id数据和undo版本链中的事务id数据,就可以找到read view创建之前所提交的数据。
追问:read view具体记录了哪些数据,具体怎么去和undo log中记录的id对比,最后找到想要的数据的?
read view视图里面记录了当前事务id、当前未提交事务(活跃事务)id列表、当前未提交事务id列表的最小值、当前最大事务id。先找到undo log第一条数据,对比事务id和read view当前事务id是否一样。。,对比事务id是不是小于最小活跃事务id。。。,然后对比事务id是不是大于最大事务id。。。,最后判断事务id是不是在活跃事务id列表里面。。
相关文章:
MySQL多版本并发控制MVCC实现原理
MVCC MVCC 是多版本并发控制方法,用来解决读和写之间的冲突,比如脏读、不可重复读问题,MVCC主要针对读操作做限制,保证每次读取到的数据都是本次读取之前的已经提交事务所修改的。 概述 当一个事务要对数据库中的数据进行selec…...
【并查集】[ABC372E] K-th Largest Connected Components 题解
题意 前置阅读:并查集算法介绍 洛谷链接 Atcoder 链接 给定 n ( 1 ≤ n ≤ 2 1 0 5 ) n(1 \leq n \leq 2\times 10^5) n(1≤n≤2105) 个点,初始没有边,您要进行以下操作: 1 a b,表示连接一条 ( a , b ) (a,b) …...
HarmonyOS面试题(持续更新中)
1、用过线程通信吗,线程是怎么进行通信的? emitter 和 eventHub 相同: 都是基于事件总线的 区别是: ① eventHub当前线程内通信 ② emitter是同一进程不同线程或者同一进程和同一线程也可以通信 2、页面和组件的生命周期 …...
QT中QWidget和QObject的区别与联系是什么
在Qt框架中,QWidget和QObject是两个核心类,它们各自扮演着不同的角色,但又紧密相连。以下是关于它们区别与联系的详细解释: 区别 基类和功能定位: QObject是Qt中所有类的基类,包括几乎所有的Qt对象。它提供…...
解决macOS安装redis以后不支持远程链接的问题
参考文档:https://blog.csdn.net/qq_37703224/article/details/142542179?spm1001.2014.3001.5501 安装的时候有个提示, 使用指定配置启动: /opt/homebrew/opt/redis/bin/redis-server /opt/homebrew/etc/redis.conf那么我们可以尝试修改这个配置文件: code /opt/homebrew/…...
2024年研究生数学建模“华为杯”E题——肘部法则、k-means聚类、目标检测(python)、ARIMA、逻辑回归、混淆矩阵(附:目标检测代码)
文章目录 一、情况介绍二、思路情况二、代码展示三、感受 一、情况介绍 前几天也是参加了研究生数学建模竞赛(也就是华为杯),也是和本校的两个数学学院的朋友在网上组的队伍。昨天(9.25)通宵干完论文(一条…...
绝了,自从用了它,我每天能多摸鱼2小时!
大家好,我是可乐。 俗话说的好:“摸鱼一时爽,一直摸鱼一直爽”。 作为一个程序员,是否有过调试代码熬到深夜?是否有过找不到解决方案而挠秃头顶? 但现在你即将要解放了,用了这款工具——秘塔…...
C语言指针系列1——初识指针
祛魅:其实指针这块儿并不难,有人说难只是因为基础到进阶没有处理好,大家要好好跟着一步一步学习,今天我们先来认识一下指针 指针定义:指针就是内存地址,指针变量是用来存放内存地址的变量,在同一…...
传神论文中心|第26期人工智能领域论文推荐
在人工智能领域的快速发展中,我们不断看到令人振奋的技术进步和创新。近期,开放传神(OpenCSG)传神社区发现了一些值得关注的成就。传神社区本周也为对AI和大模型感兴趣的读者们提供了一些值得一读的研究工作的简要概述以及它们各自…...
NLP基础1
NLP基础1 深度学习中的NLP的特征输入 1.稠密编码(特征嵌入) 稠密编码(Dense Encoding):指将离散或者高纬的稀疏数据转化为低纬度的连续、密集向量表示 特征嵌入(Feature Embedding) 也称…...
001.docker30分钟速通版
docker简介 docker就是一个用于构建(build),运行(run),传送(share)应用程序的平台做一个不恰当的类比,就是外卖平台,如果你自己做华莱士不一定好吃࿰…...
Kafka 在 Linux 下的集群配置和安装
Kafka 在 Linux 下的集群配置和安装 Apache Kafka 是一个流行的分布式流处理平台,广泛用于实时数据管道和流处理应用。本文将详细讲解如何在 Linux 环境中配置和安装 Kafka 集群,并包括通过 Docker 安装和配置 Kafka 的步骤。每个步骤都将提供详细的解释…...
Python--操作列表
1.for循环 1.1 for循环的基本语法 for variable in iterable: # 执行循环体 # 这里可以是任何有效的Python代码块这里的variable是一个变量名,用于在每次循环迭代时临时存储iterable中的下一个元素。 iterable是一个可迭代对象,比如列表(…...
JMeter(需要补充请在留言区发给我,谢谢)
一、学习工具 1、CinfigElement(HTTP Request Defaults、HTTP Header Manager、HTTP Authorization、CSV Data Set Config、User Defined Variables、JDBC Connection Configuration、HTTP Cookie Manager、Random Variable) 二、协议 1、HTTP协议(消息体数据&am…...
线程池的执行流程和配置参数总结
一、线程池的执行流程总结 提交线程任务;如果线程池中存在空闲线程,则分配一个空闲线程给任务,执行线程任务;线程池中不存在空闲线程,则线程池会判断当前线程数是否超过核心线程数(corePoolSize)…...
node-red-L3-重启指定端口的 node-red
重启指定端口 目的步骤查找正在运行的Node.js服务的进程ID(PID):停止Node.js服务:启动Node.js服务: 目的 重启指定端口的 node-red 步骤 在Linux系统中,如果你想要重启一个正在运行的Node.js服务&#x…...
(done) 使用泰勒展开证明欧拉公式
问问神奇的 GPT,how to prove euler formula? 一个答案如下:...
红队apt--邮件钓鱼
前言 欢迎来到我的博客 个人主页:北岭敲键盘的荒漠猫-CSDN博客 免责声明: 本文仅供了解攻击方手法使用,切勿用于非授权情节 初步了解邮件基础 用途方面 这个我们应该比较熟悉,最常用于验证码接收,也有一些厂商会用这个来打广告,…...
十七,Spring Boot 整合 MyBatis 的详细步骤(两种方式)
十七,Spring Boot 整合 MyBatis 的详细步骤(两种方式) 文章目录 十七,Spring Boot 整合 MyBatis 的详细步骤(两种方式)1. Spring Boot 配置 MyBatis 的详细步骤2. 最后: MyBatis 的官方文档:https://mybatis.p2hp.com/ 关于 MyBa…...
DNS协议解析
DNS协议解析 什么是DNS协议 IP地址:一长串唯一标识网络上的计算机的数字 域名:一串由点分割的字符串名字 网址包含了域名 DNS:域名解析协议 IP>域名 --反向解析 域名>IP --正向解析 域名 由ICANN管理,有级别…...
观成科技:隐蔽隧道工具Ligolo-ng加密流量分析
1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具,该工具基于TUN接口实现其功能,利用反向TCP/TLS连接建立一条隐蔽的通信信道,支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式,适应复杂网…...
深度学习在微纳光子学中的应用
深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向: 逆向设计 通过神经网络快速预测微纳结构的光学响应,替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)
HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...
Zustand 状态管理库:极简而强大的解决方案
Zustand 是一个轻量级、快速和可扩展的状态管理库,特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...
Java - Mysql数据类型对应
Mysql数据类型java数据类型备注整型INT/INTEGERint / java.lang.Integer–BIGINTlong/java.lang.Long–––浮点型FLOATfloat/java.lang.FloatDOUBLEdouble/java.lang.Double–DECIMAL/NUMERICjava.math.BigDecimal字符串型CHARjava.lang.String固定长度字符串VARCHARjava.lang…...
python如何将word的doc另存为docx
将 DOCX 文件另存为 DOCX 格式(Python 实现) 在 Python 中,你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是,.doc 是旧的 Word 格式,而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...
令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍
文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结: 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析: 实际业务去理解体会统一注…...
相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...
JDK 17 新特性
#JDK 17 新特性 /**************** 文本块 *****************/ python/scala中早就支持,不稀奇 String json “”" { “name”: “Java”, “version”: 17 } “”"; /**************** Switch 语句 -> 表达式 *****************/ 挺好的ÿ…...
大学生职业发展与就业创业指导教学评价
这里是引用 作为软工2203/2204班的学生,我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要,而您认真负责的教学态度,让课程的每一部分都充满了实用价值。 尤其让我…...
