Mysql--技术文档--MVCC(Multi-Version Concurrency Control | 多版本并发控制)

news2025/1/23 22:46:26

MVCC到底是什么

        MVCC(Multi-Version Concurrency Control)是一种并发控制机制,用于解决并发访问数据库时的数据一致性和隔离性问题。MVCC允许多个事务同时读取数据库的同一数据,而不会相互干扰或导致冲突。

        在传统的并发控制机制中,如锁定机制,事务会对读取和写入的数据进行加锁,以确保每个事务独占所需的资源。然而,这种悲观并发控制机制可能导致资源争用和性能问题,尤其是在高并发环境下。

一文读懂数据库的MVCC实现原理

 MVCC是innodb实现事务并发与回滚的重要功能!!!!!

MVCC解决了哪些问题

MVCC(Multi-Version Concurrency Control)解决了以下几个关键问题:

  1. 读-写冲突:传统的并发控制机制,如锁定机制,可能导致读取和写入操作之间的冲突。当多个事务试图同时读取和写入相同的数据时,会发生资源争用问题。MVCC通过并发控制的方式,让读取操作不受写入操作的干扰,从而避免了这种读-写冲突。

  2. 写-写冲突:在传统的并发控制机制中,当多个事务同时试图写入相同的数据时,会发生写入冲突。这可能导致数据的不一致性以及事务的回滚和重试。MVCC通过并发控制,使得每个事务都操作自己的独立版本,从而避免了写-写冲突,提高了并发性能。

  3. 隔离性问题:在多用户并发操作中,隔离性是确保事务之间互不干扰的重要属性。传统的并发控制机制,如锁定机制,可能导致事务之间的阻塞和相互等待。MVCC通过使用多个版本和快照读取,实现了事务之间的隔离性,使得事务可以并发执行而互不干扰。

  4. 性能问题:传统的并发控制机制中,加锁的方式可能导致较高的开销和资源争用,特别是在高并发环境下。MVCC采用了乐观的并发控制方式,减少了锁冲突和资源争用,从而提高了并发性能和系统吞吐量。

综上所述,MVCC通过解决读-写冲突、写-写冲突、隔离性问题和性能问题,提供了更好的并发控制机制。它通过版本管理和快照读取,使得多个事务可以并发执行而互不干扰,从而提高了数据库的性能、可用性和一致性。

MVCC底层机制-具体实现

具体的实现是,在数据库的每一行中,添加额外的三个字段:

  1. DB_TRX_ID – 记录插入或更新该行的最后一个事务的事务 ID
  2. DB_ROLL_PTR – 指向改行对应的 undolog 的指针
  3. DB_ROW_ID – 单调递增的行 ID,他就是 AUTO_INCREMENT 的主键 ID

在MVCC的实现中,使用乐观锁和额外的字段来实现并发控制。以下是对每个字段的具体解释和MVCC如何使用乐观锁的简单概述:

  1. DB_TRX_ID(事务ID):这个字段用于记录插入或更新行的最后一个事务的事务ID。每个事务在执行写操作时,都会生成一个唯一的事务ID并关联到相关数据行。这样,MVCC可以通过比较事务ID来确定事务执行期间的数据版本。

  2. DB_ROLL_PTR(undolog指针):这个字段指向对应行的undolog的指针。undolog是InnoDB存储引擎用于实现事务的撤销(undo)或回滚(rollback)操作的日志。通过保留undolog指针,MVCC可以在事务回滚或读取旧版本数据时进行快速回溯到适当的undolog。

  3. 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中的实现底层包括以下几个组成部分:

  1. 版本链:每个数据行都有一个版本链,用于存储该数据行的多个版本。版本链可以是链表或者树形结构,具体的实现取决于MySQL的版本和存储引擎。版本链中的每个版本都包含了数据的实际内容以及相关的时间戳信息。

  2. 事务的时间戳:每个事务在开始时都会被分配一个时间戳。事务的时间戳用于判断每个版本对于该事务的可见性。

  3. 数据行的锁:为了保证并发事务的一致性,MySQL使用了锁机制。在MVCC中,数据行的读锁会阻止写事务对该数据行的修改操作,而写锁会阻止其他事务对该数据行的读写操作。

  4. 读取操作的一致性视图:每个事务在执行读取操作时会创建一个一致性视图。该一致性视图会基于事务的时间戳和数据行版本的时间戳来确定每个数据行对于该事务的可见性。

不同的存储引擎在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,表示该数据已经被删除,因此不返回数据。

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

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

相关文章

CTFhub-文件上传-无验证

怎样判断一个网站是 php asp jsp 网站 首先&#xff0c;上传用哥斯拉生成 .php 文件 然后&#xff0c;用蚁剑测试连接 找到 flag_1043521020.php 文件&#xff0c;进去&#xff0c;即可发现 flag ctfhub{ee09842c786c113fb76c5542}

「Vue|网页开发|前端开发」02 从单页面到多页面网站:使用路由实现网站多个页面的展示和跳转

本文主要介绍如何使用路由控制来实现将一个单页面网站扩展成多页面网站&#xff0c;包括页面扩展的逻辑&#xff0c;vue的官方路由vue-router的基本用法以及扩展用法 文章目录 一、场景说明二、基本的页面扩展页面扩展是在扩什么创建新页面的代码&#xff0c;让页面内容变化起…

windows系统配置tcp最大连接数

打开注册表 运行->regedit HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters目录下 增加一个MaxUserPort&#xff08;默认值是5000&#xff0c;端口范围是1025至5000&#xff09;MaxUserPort设置为65534&#xff08;需重启服务器&#xff09; 执行dos命令&…

登高不系安全带自动识别

登高不系安全带自动识别采用yolov8深度学习算法框架模型&#xff0c;登高不系安全带自动识别能够自动检测和识别登高作业人员是否佩戴安全带&#xff0c;过滤其他类似物体的干扰。登高不系安全带自动识别发现有人员未佩戴安全带&#xff0c;将立即触发预警。根据YOLO的设计&…

使用PXE启动无系统盘的客户机并运行Ubuntu系统

准备 机器说明server安装pxe相关软件&#xff0c;nfs-kernel-server&#xff0c;ip192.168.1.2client1带有硬盘&#xff0c;使用iso安装ubuntu系统&#xff0c;并安装日常工作需要用到的软件&#xff0c;做好相应配置&#xff0c;安装nfs客户端&#xff1a;nfs-commonclient2没…

javacv基础03-调用本机摄像头并截图保存到本地磁盘

基于基础02 的基础上对视频进行取帧保存 代码如下&#xff1a; package com.example.javacvstudy;/*** 本地摄像头截图*/import org.bytedeco.javacv.CanvasFrame; import org.bytedeco.javacv.FrameGrabber; import org.bytedeco.javacv.OpenCVFrameConverter; import org.b…

避免常见面试错误:程序员应该注意的陷阱

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

《Flink学习笔记》——第九章 多流转换

无论是基本的简单转换和聚合&#xff0c;还是基于窗口的计算&#xff0c;我们都是针对一条流上的数据进行处理的。而在实际应用中&#xff0c;可能需要将不同来源的数据连接合并在一起处理&#xff0c;也有可能需要将一条流拆分开&#xff0c;所以经常会有对多条流进行处理的场…

​LeetCode解法汇总57. 插入区间

目录链接&#xff1a; 力扣编程题-解法汇总_分享记录-CSDN博客 GitHub同步刷题项目&#xff1a; https://github.com/September26/java-algorithms 原题链接&#xff1a;力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 描述&#xff1a; 给你一个 …

python web GUI框架-NiceGUI 教程(一)

python web GUI框架-NiceGUI 教程&#xff08;一&#xff09; streamlit可以在一些简单的场景下仍然推荐使用&#xff0c;但是streamlit实在不灵活&#xff0c;受限于它的核心机制&#xff0c;NiceGUI是一个灵活的web框架&#xff0c;可以做web网站也可以打包成独立的exe。 基…

科研小工具|心输出量(超声)(cardiac output,CO)

​ 简介 心输出量&#xff08;cardiac output&#xff0c;CO&#xff09;是指左或右心室每分钟泵出的血液量。即心率与每搏出量的乘积。如心率以75次/分钟计算&#xff0c;则心排出量在男性为5~6L&#xff0c;女性略低些。心排出量随着机体代谢和活动情况而变化。在肌肉运动、…

783页19万字行政服务中心一网通办政务服务应用平台建设方案

导读&#xff1a;原文《783页19万字行政服务中心一网通办政务服务应用平台建设方案》&#xff08;获取来源见文尾&#xff09;&#xff0c;本文精选其中精华及架构部分&#xff0c;逻辑清晰、内容完整&#xff0c;为快速形成售前方案提供参考。以下是部分内容&#xff0c; 第三…

阿里巴巴FastJson包的使用心得

阿里巴巴FastJson包的使用心得 1.FastJson简介2.FastJson特性3.引入FastJson4.FastJson中的一些对象&#xff08;1&#xff09;JSONObject&#xff08;2&#xff09;JSONArray&#xff08;3&#xff09;SerializeWriter 4.FastJson中的一些操作&#xff08;1&#xff09; 将Jav…

配置uniapp调试环境

目录 uni-app介绍 uni-app开发工具HBuilderX 创建项目前提条件 uni-app项目结构 配置mumu模拟器 uni-app生命周期 1.应用生命周期 小程序规范 2.页面生命周期-小程序规范 3.组件生命周期 vue规范 uni-app登录按钮方法 uni-app发布安卓app uni-app介绍 uni-app 是一个…

深入理解ArrayList的动态扩容机制及应用

在java编程中&#xff0c;数据结构起着至关重要的作用&#xff0c;而ArrayList作为一种常用的动态数组&#xff0c;为我们在处理数据时提供了便利。其中&#xff0c;其独特的动态扩容机制更是为其赢得了广泛的应用。我们不管在工作还是面试中&#xff0c;都会遇到ArrayList&…

Docker拉取RocketMQ及可视化界面

本文介绍Docker拉取RocketMQ及可视化界面操作步骤 Linux下安装Docker请参考&#xff1a;Linux安装Docker 文章目录 安装namesrv创建挂载目录授权相关权限拉取镜像运行容器查看运行情况 安装Broker创建挂载目录及配置文件目录授权相关权限创建配置文件运行容器查看运行情况 安装…

网络编程套接字(3): 简单的TCP网络程序

文章目录 网络编程套接字(3)4. 简单的TCP网络程序4.1 服务端创建(1) 创建套接字(2) 绑定端口(3) 监听(4) 获取新连接(5) 处理读取与写入 4.2 客户端创建(1)连接服务器 4.3 代码编写(1) v1__简单发送消息(2) v2_多进程版本(3) v3_多线程版本(4) v4_线程池版本 网络编程套接字(3)…

博客系统后端(项目系列2)

目录 前言 &#xff1a; 1.准备工作 1.1创建项目 1.2引入依赖 1.3创建必要的目录 2.数据库设计 2.1博客数据 2.2用户数据 3.封装数据库 3.1封装数据库的连接操作 3.2创建两个表对应的实体类 3.3封装一些必要的增删改查操作 4.前后端交互逻辑的实现 4.1博客列表页 …

中国建筑出版传媒许少辉博士八一新书乡村振兴战略下传统村落文化旅游设计日京东当当畅销榜自由营九三学

中国建筑出版传媒许少辉博士八一新书乡村振兴战略下传统村落文化旅游设计日京东当当畅销榜自由营九三学

大数据Flink(六十九):SQL 数据类型

文章目录 SQL 数据类型 一、原子数据类型 二、​​​​​​复合数据类型 SQL 数据类型 在介绍完一些基本概念之后,我们来认识一下