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管理,有级别…...
idea大量爆红问题解决
问题描述 在学习和工作中,idea是程序员不可缺少的一个工具,但是突然在有些时候就会出现大量爆红的问题,发现无法跳转,无论是关机重启或者是替换root都无法解决 就是如上所展示的问题,但是程序依然可以启动。 问题解决…...
MongoDB学习和应用(高效的非关系型数据库)
一丶 MongoDB简介 对于社交类软件的功能,我们需要对它的功能特点进行分析: 数据量会随着用户数增大而增大读多写少价值较低非好友看不到其动态信息地理位置的查询… 针对以上特点进行分析各大存储工具: mysql:关系型数据库&am…...
Cesium1.95中高性能加载1500个点
一、基本方式: 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...
数据链路层的主要功能是什么
数据链路层(OSI模型第2层)的核心功能是在相邻网络节点(如交换机、主机)间提供可靠的数据帧传输服务,主要职责包括: 🔑 核心功能详解: 帧封装与解封装 封装: 将网络层下发…...
Python如何给视频添加音频和字幕
在Python中,给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加,包括必要的代码示例和详细解释。 环境准备 在开始之前,需要安装以下Python库:…...
代理篇12|深入理解 Vite中的Proxy接口代理配置
在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...
学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”
2025年#高考 将在近日拉开帷幕,#AI 监考一度冲上热搜。当AI深度融入高考,#时间同步 不再是辅助功能,而是决定AI监考系统成败的“生命线”。 AI亮相2025高考,40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕,江西、…...
基于Java+MySQL实现(GUI)客户管理系统
客户资料管理系统的设计与实现 第一章 需求分析 1.1 需求总体介绍 本项目为了方便维护客户信息为了方便维护客户信息,对客户进行统一管理,可以把所有客户信息录入系统,进行维护和统计功能。可通过文件的方式保存相关录入数据,对…...
GruntJS-前端自动化任务运行器从入门到实战
Grunt 完全指南:从入门到实战 一、Grunt 是什么? Grunt是一个基于 Node.js 的前端自动化任务运行器,主要用于自动化执行项目开发中重复性高的任务,例如文件压缩、代码编译、语法检查、单元测试、文件合并等。通过配置简洁的任务…...
站群服务器的应用场景都有哪些?
站群服务器主要是为了多个网站的托管和管理所设计的,可以通过集中管理和高效资源的分配,来支持多个独立的网站同时运行,让每一个网站都可以分配到独立的IP地址,避免出现IP关联的风险,用户还可以通过控制面板进行管理功…...
