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

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,具体有如下四个字段:

  1. creator_trx_id,创建当前Read View的事务ID
  2. trx_ids,表示在生成ReadView时当前系统中活跃的读写事务的事务id列表。
  3. min_limit_trx_id,活跃的事务中最小的事务id
  4. max_trx_id,表示生成ReadView时系统中应该分配给下一个事务的id值。low_limit_id是系统最大的事务id值,这里要注意是系统中的所有事务id,不仅包含正在活跃的事务id、还包含之前已提交的事务id。

注意:

  1. 只有在对表中的记录做改动时(执行INSERT、DELETE、UPDATE这些语句时)才会为事务分配事务id,否则在一个只读事务中的事务id值都默认为0。
  2. 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工作流程

  1. 某个事务执行select查找时,首先根据数据行的某个字段获取事务自己的版本号,也就是事务ID;
  2. 然后创建ReadView;
  3. 查询得到最新数据,然后与ReadView中的事务版本号按照一定规则进行比较;
  4. 如果不符合ReadView规则,就需要从Undo Log 中获取历史快照;
  5. 一直往前查找,直到返回符合规则的数据。

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)应用程序的平台做一个不恰当的类比,就是外卖平台,如果你自己做华莱士不一定好吃&#xff0…...

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&#xff09…...

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管理,有级别&#xf…...

19c补丁后oracle属主变化,导致不能识别磁盘组

补丁后服务器重启,数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后,存在与用户组权限相关的问题。具体表现为,Oracle 实例的运行用户(oracle)和集…...

最新SpringBoot+SpringCloud+Nacos微服务框架分享

文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的,根据Excel列的需求预估的工时直接打骨折,不要问我为什么,主要…...

C++.OpenGL (10/64)基础光照(Basic Lighting)

基础光照(Basic Lighting) 冯氏光照模型(Phong Lighting Model) #mermaid-svg-GLdskXwWINxNGHso {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GLdskXwWINxNGHso .error-icon{fill:#552222;}#mermaid-svg-GLd…...

AI,如何重构理解、匹配与决策?

AI 时代,我们如何理解消费? 作者|王彬 封面|Unplash 人们通过信息理解世界。 曾几何时,PC 与移动互联网重塑了人们的购物路径:信息变得唾手可得,商品决策变得高度依赖内容。 但 AI 时代的来…...

推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)

推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...

【MATLAB代码】基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),附源代码|订阅专栏后可直接查看

文章所述的代码实现了基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),针对传感器观测数据中存在的脉冲型异常噪声问题,通过非线性加权机制提升滤波器的抗干扰能力。代码通过对比传统KF与MCC-KF在含异常值场景下的表现,验证了后者在状态估计鲁棒性方面的显著优…...

Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析

Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析 一、第一轮基础概念问题 1. Spring框架的核心容器是什么?它的作用是什么? Spring框架的核心容器是IoC(控制反转)容器。它的主要作用是管理对…...

基于鸿蒙(HarmonyOS5)的打车小程序

1. 开发环境准备 安装DevEco Studio (鸿蒙官方IDE)配置HarmonyOS SDK申请开发者账号和必要的API密钥 2. 项目结构设计 ├── entry │ ├── src │ │ ├── main │ │ │ ├── ets │ │ │ │ ├── pages │ │ │ │ │ ├── H…...

自然语言处理——文本分类

文本分类 传统机器学习方法文本表示向量空间模型 特征选择文档频率互信息信息增益(IG) 分类器设计贝叶斯理论:线性判别函数 文本分类性能评估P-R曲线ROC曲线 将文本文档或句子分类为预定义的类或类别, 有单标签多类别文本分类和多…...

前端高频面试题2:浏览器/计算机网络

本专栏相关链接 前端高频面试题1:HTML/CSS 前端高频面试题2:浏览器/计算机网络 前端高频面试题3:JavaScript 1.什么是强缓存、协商缓存? 强缓存: 当浏览器请求资源时,首先检查本地缓存是否命中。如果命…...