Mysql--技术文档--MVCC(Multi-Version Concurrency Control | 多版本并发控制)
MVCC到底是什么
MVCC(Multi-Version Concurrency Control)是一种并发控制机制,用于解决并发访问数据库时的数据一致性和隔离性问题。MVCC允许多个事务同时读取数据库的同一数据,而不会相互干扰或导致冲突。
在传统的并发控制机制中,如锁定机制,事务会对读取和写入的数据进行加锁,以确保每个事务独占所需的资源。然而,这种悲观并发控制机制可能导致资源争用和性能问题,尤其是在高并发环境下。
MVCC是innodb实现事务并发与回滚的重要功能!!!!!
MVCC解决了哪些问题
MVCC(Multi-Version Concurrency Control)解决了以下几个关键问题:
-
读-写冲突:传统的并发控制机制,如锁定机制,可能导致读取和写入操作之间的冲突。当多个事务试图同时读取和写入相同的数据时,会发生资源争用问题。MVCC通过并发控制的方式,让读取操作不受写入操作的干扰,从而避免了这种读-写冲突。
-
写-写冲突:在传统的并发控制机制中,当多个事务同时试图写入相同的数据时,会发生写入冲突。这可能导致数据的不一致性以及事务的回滚和重试。MVCC通过并发控制,使得每个事务都操作自己的独立版本,从而避免了写-写冲突,提高了并发性能。
-
隔离性问题:在多用户并发操作中,隔离性是确保事务之间互不干扰的重要属性。传统的并发控制机制,如锁定机制,可能导致事务之间的阻塞和相互等待。MVCC通过使用多个版本和快照读取,实现了事务之间的隔离性,使得事务可以并发执行而互不干扰。
-
性能问题:传统的并发控制机制中,加锁的方式可能导致较高的开销和资源争用,特别是在高并发环境下。MVCC采用了乐观的并发控制方式,减少了锁冲突和资源争用,从而提高了并发性能和系统吞吐量。
综上所述,MVCC通过解决读-写冲突、写-写冲突、隔离性问题和性能问题,提供了更好的并发控制机制。它通过版本管理和快照读取,使得多个事务可以并发执行而互不干扰,从而提高了数据库的性能、可用性和一致性。
MVCC底层机制-具体实现
具体的实现是,在数据库的每一行中,添加额外的三个字段:
- DB_TRX_ID – 记录插入或更新该行的最后一个事务的事务 ID
- DB_ROLL_PTR – 指向改行对应的 undolog 的指针
- DB_ROW_ID – 单调递增的行 ID,他就是 AUTO_INCREMENT 的主键 ID
在MVCC的实现中,使用乐观锁和额外的字段来实现并发控制。以下是对每个字段的具体解释和MVCC如何使用乐观锁的简单概述:
-
DB_TRX_ID(事务ID):这个字段用于记录插入或更新行的最后一个事务的事务ID。每个事务在执行写操作时,都会生成一个唯一的事务ID并关联到相关数据行。这样,MVCC可以通过比较事务ID来确定事务执行期间的数据版本。
-
DB_ROLL_PTR(undolog指针):这个字段指向对应行的undolog的指针。undolog是InnoDB存储引擎用于实现事务的撤销(undo)或回滚(rollback)操作的日志。通过保留undolog指针,MVCC可以在事务回滚或读取旧版本数据时进行快速回溯到适当的undolog。
-
DB_ROW_ID(行ID):这个字段是单调递增的行ID,通常用作AUTO_INCREMENT主键ID。它提供了一种方式来唯一标识每一行,以便MVCC在处理并发操作时进行准确定位。
MVCC使用乐观锁来确保对数据行的并发访问不会产生冲突。它通过比较事务的启动时间戳(或序列号)和数据行的事务ID来判断是否存在并发冲突。当一个事务启动时,会获取所有需要读取或修改的数据行的版本信息,包括DB_TRX_ID和DB_ROLL_PTR字段。在读取或修改数据时,MVCC会使用这些版本信息进行验证,以确定是否访问的是合适的数据版本。
如果在事务执行期间,发现其他事务已经修改了数据行的版本(事务ID不一致),则会回滚当前事务,因为它访问的是过期的数据版本。这种方式可以避免读-写冲突和写-写冲突,提供了一致的数据访问和更新。
需要注意的是,MVCC的具体实现可能会有一些细微的差异,因为不同的数据库管理系统可能采用不同的方式来处理并发控制。但是上述提到的字段和基本思想是MVCC的常见实现方式之一。
总而言之,MVCC使用乐观锁和额外的字段来实现并发控制。通过比较事务ID和版本信息,MVCC可以识别并处理并发访问冲突,从而确保数据的一致性和隔离性。
悲观锁和乐观锁的对比
Mysql--技术文档--悲观锁、乐观锁-《控制并发机制简单认知、深度理解》_一单成的博客-CSDN博客
MVCC实现的三大要素
使用范围:
首先要明白mvcc只在REPEATABLE READ(可重复读) 和 READ COMMITTED(已读提交)这两个隔离级别下面使用。
REPEATABLE(可重复的)、COMMITTED(承诺)
MVCC实现原理是两个隐式字段、undo日志、Read view来实现的。
1. 隐式字段
在Innodb存储引擎中,在有聚簇索引的情况下每一行记录中都会隐藏俩个字段,如果没有聚簇索引则还有一个6byte的隐藏主键。
这俩个隐藏列一个记录的是何时被创建的,一个记录的是什么时候被删除。
这里不要理解为是记录的是时间,存储的是事务ID。
俩个隐式字段为DB_TRX_ID,DB_ROLL_PTR,没有聚簇索引还会有DB_ROW_ID这个字段。
- DB_TRX_ID:记录创建这条数据上次修改它的事务 ID
- DB_ROLL_PTR:回滚指针,指向这条记录的上一个版本
隐式字段实际还有一个delete flag字段,即记录被更新或删除,这里的删除并不代表真的删除,而是将这条记录的delete flag改为true
MySQL提供了逻辑删除的方式,可以通过在表中添加一个额外的列(例如delete_flag字段)来实现。逻辑删除是将记录标记为已删除的状态,而不是将其物理删除。这种方式保留了记录的历史信息,并且可以根据需要恢复或审计已删除的记录。在执行查询操作时,可以使用查询条件来过滤掉已标记为删除的记录。
2. undo log(回滚日志)
之前对undo log的作用只提到了回滚操作实现原子性,现在需要知道的另一个作用就是实现MVCC多版本控制器。
undo log细分为俩种,insert时产生的undo log、update,delete时产生的undo log
在Innodb中insert产生的undo log在提交事务之后就会被删除,因为新插入的数据没有历史版本,所以无需维护undo log。
update和delete操作产生的undo log都属于一种类型,在事务回滚时需要,而且在快照读时也需要,则需要维护多个版本信息。只有在快照读和事务回滚不涉及该日志时,对应的日志才会被purge
线程统一删除。
purge线程会清理undo log的历史版本,同样也会清理del flag标记的记录。
undo log在mvcc中的作用
写到这里关于undo log在mvcc中的作用估计还是蒙圈的。
undo log保存的是一个版本链,也就是使用DB_ROLL_PTR这个字段来连接的。
当数据库执行一个select语句时会产生一致性视图read view
。
那么这个read view是由查询时所有未提交事务ID组成的数组,数组中最小的事务ID为min_id和已创建的最大事务ID为max_id组成,查询的数据结果需要跟read-view做比较从而得到快照结果。
所以说undo log在mvcc中的作用就是为了根据存储的事务ID和一致性视图做对比,从而得到快照结果。
3、undo log底层实现
在原始数据执行一条语句之后将undo log记录发生变化。
也就是说在一条语句更新的时候会把原有的数据拷贝到undo log日志中。
然后使用指针在最新的记录和旧的记录连接一条线,也就是存放undo log日志的指针地址。
最后需要的时候通过指针来找到历史数据。
Undo Log(回滚日志)是用于实现事务的原子性和一致性的一个重要组成部分。它是在事务执行期间记录数据修改操作的地方,并可用于回滚事务或恢复数据到之前的状态。
Undo Log的底层实现是通过使用一种称为"回滚段"的数据结构。回滚段是专门用于存储Undo Log的数据结构,它位于表空间中的一个特殊位置。
每个事务在执行修改操作前,会在Undo Log中为所涉及的数据行生成一个“回滚记录”。这个回滚记录存储了修改前的数据值(原始数据值),以及用于回滚操作的其他相关信息。
当事务需要回滚时,Undo Log可以通过相反的操作撤消该事务的修改。它会使用回滚记录中的原始数据值来将数据恢复到事务开始之前的状态。
此外,Undo Log还用于处理并发事务之间的读取一致性。在MVCC中,读取操作需要使用Undo Log来判断某个数据版本是否对当前事务可见。
总的来说,Undo Log的底层实现基于回滚段数据结构,它在事务执行期间记录数据的修改操作,并在事务回滚或 MVCC 快照读取时使用这些信息。这个机制确保了事务的原子性、一致性和隔离性,并为数据库提供了数据恢复和读取一致性的支持。
4、read-view
MySQL中的read-view(读视图)。在MySQL中,视图是一种虚拟表,它是根据一个或多个表的查询结果创建的。视图可以被看作是存储在数据库中的虚拟表格,可以像表一样查询和使用。
使用read-view可以实现以下功能:
-
简化复杂的查询:通过创建视图,你可以将复杂的查询逻辑封装到一个简单的视图中,然后在查询中使用该视图,从而简化查询语句。
-
访问权限控制:通过使用视图,你可以只向用户展示需要的数据,而隐藏底层表的细节。这提供了更好的安全性和数据访问控制。
-
数据的逻辑组织:通过创建视图,你可以根据业务需求将表的数据进行组织和过滤,从而更好地管理和理解数据。
总之,read-view(读视图)是在MySQL中创建的一种虚拟表,可以用于简化查询、控制数据访问权限以及逻辑组织数据。
当执行SQL语句查询时会产生一致性视图,也就是read-view,它是由查询的那一时间所有未提交事务ID组成的数组,和已经创建的最大事务ID组成的。
在这个数组中最小的事务ID被称之为min_id,最大事务ID被称之为max_id,查询的数据结果要根据read-view做对比从而得到快照结果。
阿丹理解:
这个概念其实就是在mysql中mvcc中的类似于快照的概念,因为innodb不是使用的是mvcc+乐观锁来解决并发问题嘛,对于操作进行锁不对读来锁,然后在进行操作的时候去对比之前的改之前的版本的。
这个概念对于mvcc的作用是在一个事务开始时,它会根据自己的Read-View创建一个快照,并在整个事务期间使用这个快照进行读取操作。这个快照包含了事务开始时数据库的一个一致视图。
5、版本链对比规则
MVCC在MySQL中的实现底层包括以下几个组成部分:
-
版本链:每个数据行都有一个版本链,用于存储该数据行的多个版本。版本链可以是链表或者树形结构,具体的实现取决于MySQL的版本和存储引擎。版本链中的每个版本都包含了数据的实际内容以及相关的时间戳信息。
-
事务的时间戳:每个事务在开始时都会被分配一个时间戳。事务的时间戳用于判断每个版本对于该事务的可见性。
-
数据行的锁:为了保证并发事务的一致性,MySQL使用了锁机制。在MVCC中,数据行的读锁会阻止写事务对该数据行的修改操作,而写锁会阻止其他事务对该数据行的读写操作。
-
读取操作的一致性视图:每个事务在执行读取操作时会创建一个一致性视图。该一致性视图会基于事务的时间戳和数据行版本的时间戳来确定每个数据行对于该事务的可见性。
不同的存储引擎在MVCC的实现上可能会有细微的差异,因为存储引擎负责管理数据的存储和访问。例如,InnoDB存储引擎使用了undo日志和read-view机制来实现MVCC,而MyISAM存储引擎则没有内置的MVCC实现。
如果落在trx_id<min_id,表示此版本是已经提交的事务生成的,由于事务已经提交所以数据是可见的
如果落在trx_id>max_id,表示此版本是由将来启动的事务生成的,是肯定不可见的
若在min_id<=trx_id<=max_id时
- 如果row的trx_id在数组中,表示此版本是由还没提交的事务生成的,不可见,但是当前自己的事务是可见的
- 如果row的trx_id不在数组中,表明是提交的事务生成了该版本,可见
在这里还有一个特殊情况那就是对于已经删除的数据,在之前的undo log日志讲述时说了update和delete是同一种类型的undo log,同样也可以认为delete就是update的特殊情况。
当删除一条数据时会将版本链上最新的数据复制一份,然后将trx_id修改为删除时的trx_id,同时在该记录的头信息中存在一个delete flag标记,将这个标记写上true,用来表示当前记录已经删除。
在查询时按照版本链的规则查询到对应的记录,如果delete flag标记位为true,意味着数据已经被删除,则不返回数据。
trx_id:
代表事务ID,用于标识每个事务的唯一性。它可以用于确定事务的开始时间和提交时间。
min_id:
最小可见事务ID。它表示正在执行的事务所能看到的最早提交的事务的ID。事务ID小于"min_id"的所有事务都是已经提交的事务,对于当前事务而言,它们的修改是可见的。
总结:
"trx_id"和"min_id"是MVCC中用于判断数据对于当前事务的可见性的重要标识。
注意:
对于已经删除的数据,在MVCC中会将最新版本的数据进行复制,并将"trx_id"修改为删除时的"trx_id"。同时,在记录的头信息中设置一个"delete flag"标记来表示该记录已经被删除。当查询时根据版本链的规则进行查询,如果"delete flag"标记为true,表示该数据已经被删除,因此不返回数据。
相关文章:

Mysql--技术文档--MVCC(Multi-Version Concurrency Control | 多版本并发控制)
MVCC到底是什么 MVCC(Multi-Version Concurrency Control)是一种并发控制机制,用于解决并发访问数据库时的数据一致性和隔离性问题。MVCC允许多个事务同时读取数据库的同一数据,而不会相互干扰或导致冲突。 在传统的并发控制机制中…...

全网都在用的nnUNet V2版本改进了啥,怎么安装?(一)
nnUNet,这个医学领域的分割巨无霸!在论文和比赛中随处可见他的身影。大家对于nnUNet v1版本的教程都赞不绝口,因为它简单易懂、详细全面,让很多朋友都轻松掌握了使用方法。 最近,我也抽出时间仔细研究了nnUNet v2,并全…...

iOS开发Swift-4-IBAction,group,音乐播放器-木琴App
1.使用素材创建木琴App的UI。 2.连接IBAction。 其余按钮直接拖拽到play里边。 当鼠标置于1处时2处显示如图,表示成功。当用户按下任一按钮都会触发play中的内容。 3.将7个按钮的View中的Tag值分别调为1、2、3、4、5、6、7. 4.将音频文件拖入项目文件中。 Create gr…...
【linux】pid 文件的作用ing
文章目录 一. pid文件简介1. pid 文件是什么2. 作用 二. pid文件的使用 一. pid文件简介 1. pid 文件是什么 打开系统(Linux) 的 “/var/run/” 目录可以看到有很多已 “.pid” 为结尾的文件,只有一行,它记录的是相应进程的 pid,即进程号。…...

K8s简介之什么是K8s
目录 1.概述 2.什么是容器引擎? 3.什么是容器 4.什么是容器编排? 5.容器编排工具 6.到底什么是K8s? 7.为什么市场推荐K8s 8.K8s架构 9.K8s组件 Pods API 服务器 调度器 控制器管理器 Etcd 节点 Kubelet Kube代理 Kubectl 1.概述 Kub…...

说说Flink双流join
分析&回答 Flink双流JOIN主要分为两大类 一类是基于原生State的Connect算子操作另一类是基于窗口的JOIN操作。其中基于窗口的JOIN可细分为window join和interval join两种。 基于原生State的Connect算子操作 实现原理:底层原理依赖Flink的State状态存储&…...

I2C与I3C的对比
I2C与I3C的对比 电气特性 I2C 1.半双工 2.串行数据线(SDA)和串行时钟线(SCL) 3.数据线漏极开路,即I2C接口接上拉电阻 4.I2C总线运行速度:**标准模式100kbit/s,快速模式400kbit/s,快速模式plus 1Mbit/s,**高速模式…...

睿趣科技:抖音开小店大概多久可以做起来
随着移动互联网的快速发展,社交媒体平台成为了人们分享生活、交流信息的主要渠道之一。在众多社交平台中,抖音以其独特的短视频形式和强大的用户粘性受到了广泛关注。近年来,越来越多的人通过在抖音上开设小店来实现创业梦想,这种…...
CCF-CSP 26次 第三题【角色授权】
计算机软件能力认证考试系统 20分: #include<bits/stdc.h> using namespace std; const int N440; int n,m,q,nv,no,nn,ns,ng; struct Node {string name;map<string,int>op;map<string,int>res_kind;map<string,int>res_name; }role[N];…...

Ansible学习笔记11
Command和Shell模块: 两个模块都是用于执行Linux命令的,这个对于命令熟悉的工程师来说,用起来非常high。 Shell模块跟Command模块差不多(Command模块不能执行一类$HOME、> 、<、| 等符号,但是Shell是可以的。&…...

Vue中如何为Echarts统计图设置数据
在前端界面接收后端数据后,将数据赋值给ECharts中的data时出现了,数据读取失败的问题(可能是由于数据渲染的前后顺序问题)。后通过如下方式进行了解决: 1、接下来将介绍UserController中的countUsers方法,…...

力扣141. 环形链表
141. 环形链表 简单 2K 相关企业 给你一个链表的头节点 head ,判断链表中是否有环。 如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链…...

4.1 链式栈StackT
C关键词:内部类/模板类/头插 C自学精简教程 目录(必读) C数据结构与算法实现(目录) 栈的内存结构 空栈: 有一个元素的栈: 多个元素的栈: 成员函数说明 0 clear 清空栈 clear 函数负责将栈的对内存释放…...
算法练习(10):牛客在线编程10 贪心算法
package jz.bm;import java.util.ArrayList; import java.util.Arrays;public class bm10 {/*** BM95 分糖果问题*/public int candy (int[] arr) {int res 0;int n arr.length;int[] nums new int[n];//每个人都分配一个糖果for (int i 0; i < n; i) {nums[i] 1;}//从…...
Java8新特性1——函数式接口lambda表达式
Java8新特性1——函数式接口&lambda表达式 注:以下内容基于Java 8,所有代码都已在Java 8环境下测试通过 目录: Java8新特性1——函数式接口&lambda表达式方法引用Stream 1. 函数式接口 如果在一个接口中,有且只有一个抽…...

文本标注技术方案(NLP标注工具)
Doccano doccano 是一个面向人类的开源文本注释工具。它为文本分类、序列标记和序列到序列任务提供注释功能。您可以创建用于情感分析、命名实体识别、文本摘要等的标记数据。只需创建一个项目,上传数据,然后开始注释。您可以在数小时内构建数据集。 支持…...
03-使用一个不可变对象作为key,红黑树怎么比较大小?
使用一个不可变对象作为key,红黑树怎么比较大小? 答:Java 中的红黑树是通过左旋、右旋的方式来维护树的平衡性,而左旋、右旋又依赖于节点大小的比较。对于使用不可变对象作为key实际上是可以的,因为比较key的大小本身…...
2021江苏省赛热身赛 C Magic Rabbit(数形结合)
2021江苏省赛热身赛 C Magic Rabbit(数形结合) Magic Rabbit 非常好且巧妙地一道题。 大意:给出三种溶液 , 三种溶液分别含有不同浓度的 x ,y 两种物质。 溶液x (mg/ml)y (mg/ml)溶液1x1y1溶液2x2y2溶液3x3y3 给出 Q 组询问 ,…...
AES加密(2):AES代码实现解析
在我的上一篇文章AES基础知识和计算过程中,大概介绍了AES(Rijndael)加密的整个过程。那么在这一篇文章中,就来看一下AES在代码中是如何实现的,也有助于我们理解其中的一些细节。 本篇文章所用的AES代码来源于Szymon Stefanek的开源C代码 文章…...

SpringBoot项目通过分词器生成词云
目录 前言一、词云是什么?二、使用步骤1.引入依赖2.application.yml3.Controller4.分词工具类4.词云生成工具类、支持输出文件和字节流 注意 前言 公司项目涉及到员工任务管理,需要从员工任务中获取任务信息生成个人词云图,可以把员工任务中…...
uniapp 对接腾讯云IM群组成员管理(增删改查)
UniApp 实战:腾讯云IM群组成员管理(增删改查) 一、前言 在社交类App开发中,群组成员管理是核心功能之一。本文将基于UniApp框架,结合腾讯云IM SDK,详细讲解如何实现群组成员的增删改查全流程。 权限校验…...
【杂谈】-递归进化:人工智能的自我改进与监管挑战
递归进化:人工智能的自我改进与监管挑战 文章目录 递归进化:人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管?3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...
【Linux】C语言执行shell指令
在C语言中执行Shell指令 在C语言中,有几种方法可以执行Shell指令: 1. 使用system()函数 这是最简单的方法,包含在stdlib.h头文件中: #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...
Linux云原生安全:零信任架构与机密计算
Linux云原生安全:零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言:云原生安全的范式革命 随着云原生技术的普及,安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测,到2025年,零信任架构将成为超…...

Map相关知识
数据结构 二叉树 二叉树,顾名思义,每个节点最多有两个“叉”,也就是两个子节点,分别是左子 节点和右子节点。不过,二叉树并不要求每个节点都有两个子节点,有的节点只 有左子节点,有的节点只有…...

短视频矩阵系统文案创作功能开发实践,定制化开发
在短视频行业迅猛发展的当下,企业和个人创作者为了扩大影响力、提升传播效果,纷纷采用短视频矩阵运营策略,同时管理多个平台、多个账号的内容发布。然而,频繁的文案创作需求让运营者疲于应对,如何高效产出高质量文案成…...
Java求职者面试指南:计算机基础与源码原理深度解析
Java求职者面试指南:计算机基础与源码原理深度解析 第一轮提问:基础概念问题 1. 请解释什么是进程和线程的区别? 面试官:进程是程序的一次执行过程,是系统进行资源分配和调度的基本单位;而线程是进程中的…...

mac 安装homebrew (nvm 及git)
mac 安装nvm 及git 万恶之源 mac 安装这些东西离不开Xcode。及homebrew 一、先说安装git步骤 通用: 方法一:使用 Homebrew 安装 Git(推荐) 步骤如下:打开终端(Terminal.app) 1.安装 Homebrew…...

CVPR2025重磅突破:AnomalyAny框架实现单样本生成逼真异常数据,破解视觉检测瓶颈!
本文介绍了一种名为AnomalyAny的创新框架,该方法利用Stable Diffusion的强大生成能力,仅需单个正常样本和文本描述,即可生成逼真且多样化的异常样本,有效解决了视觉异常检测中异常样本稀缺的难题,为工业质检、医疗影像…...
规则与人性的天平——由高考迟到事件引发的思考
当那位身着校服的考生在考场关闭1分钟后狂奔而至,他涨红的脸上写满绝望。铁门内秒针划过的弧度,成为改变人生的残酷抛物线。家长声嘶力竭的哀求与考务人员机械的"这是规定",构成当代中国教育最尖锐的隐喻。 一、刚性规则的必要性 …...