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

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,表示该数据已经被删除,因此不返回数据。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【深度解析】朗逸与宝来汽车:哪款更适合你?

在汽车市场中&#xff0c;朗逸和宝来都是非常受欢迎的车型。它们各自都有独特的优点和缺点&#xff0c;那么&#xff0c;究竟哪款车更适合你呢&#xff1f;让我们一起来深度解析一下。 朗逸&#xff0c;作为大众的入门级车型&#xff0c;以其稳定的性能和较高的性价比赢得了消费…

爬虫逆向实战(二十四)--某鸟记录中心

一、数据接口分析 主页地址&#xff1a;某鸟记录中心 1、抓包 通过抓包可以发现数据接口是front/record/search/page 2、判断是否有加密参数 请求参数是否加密&#xff1f; 通过查看“载荷”模块可以发现&#xff0c;请求参数是加密的 请求头是否加密&#xff1f; 通过查…

Android Studio开发之路 (五)导入OpenCV以及报错解决

一、步骤 官网下载opencv包&#xff08;我下的是4.7.0&#xff09;并解压&#xff0c;openvc官网 先创建一个空项目&#xff0c;简单跑一下能正常输出helloworld 点击file->new->Import Module选择解压之后的opencv-android-sdk文件夹中的SDk文件夹&#xff0c; modu…

docker搭建owncloud,Harbor,构建镜像

1、使用mysql:5.6和 owncloud 镜像&#xff0c;构建一个个人网盘。 拉取镜像 docker pull owncloud docker pull mysql:5.6 2、安装搭建私有仓库 Harbor 1.下载docker-compose 2.安装harbor 3.编辑 harbor.yml文件 使用./intall.sh安装 4.登录 3、编写Dockerfile制作Web应用系…

Java 程序打印 OpenCV 的版本

我们可以使用 Java 程序来使用 OpenCV。 OpenCV 的使用需要动态库的加载才可以。 加载动态库 到 OpenCV 的官方网站上下载最新的发布版本。 Windows 下载的是一个可执行文件&#xff0c;没关系&#xff0c;这个可执行文件是一个自解压程序。 当你运行以后会提示你进行解压。…

解决抖音semi-ui的Input无法获取到onChange事件

最近在使用semi-ui框架的Input实现一个上传文件功能时遇到了坑&#xff0c;就是无法获取到onChange事件&#xff0c;通过console查看只是拿到了一个文件名。但若是把<Input>换成原生的<input>&#xff0c;就可以正常获取到事件。仔细看了下官方文档&#xff0c;发现…

Windows 转 mac 记录

初次从Windows转mac可能会不适应&#xff0c;建议先看看 【6分钟搞定MacBook】不懂时无所适从&#xff0c;学会后越用越爽&#xff01;_哔哩哔哩_bilibili 我主要是做一些补充记录 1、Windows的右键等于mac的双击触控板、control单击触控板 2、运行中的应用下方会有一个点&…

时序预测 | MATLAB实现基于PSO-BiLSTM、BiLSTM时间序列预测对比

时序预测 | MATLAB实现基于PSO-BiLSTM、BiLSTM时间序列预测对比 目录 时序预测 | MATLAB实现基于PSO-BiLSTM、BiLSTM时间序列预测对比效果一览基本描述程序设计参考资料 效果一览 基本描述 MATLAB实现基于PSO-BiLSTM、BiLSTM时间序列预测对比。 1.Matlab实现PSO-BiLSTM和BiLSTM…

微信小程序分享后真机参数获取不到和部分参数不能获取问题问题解决

微信小程序的很多API&#xff0c;都是BUG&#xff0c;近期开发小程序就遇到了分享后开发工具可以获取参数&#xff0c;但是真机怎么都拿不到参数的问题 一、真机参数获取不到问题解决 解决方式&#xff1a; 在onLoad(options) 中。 onLoad方法中一定要有options 这个参数。…

Python爬虫框架之快速抓取互联网数据详解

概要 Python爬虫框架是一个能够帮助我们快速抓取互联网数据的工具。在互联网时代&#xff0c;信息爆炸式增长&#xff0c;人们越来越需要一种快速获取信息的方式。而Python爬虫框架就能够帮助我们完成这个任务&#xff0c;它可以帮助我们快速地从互联网上抓取各种数据&#xf…

Java并发编程第6讲——线程池(万字详解)

Java中的线程池是运用场景最多的并发框架&#xff0c;几乎所有需要异步或并发执行任务的程序都可以使用线程池&#xff0c;本篇文章就详细介绍一下。 一、什么是线程池 定义&#xff1a;线程池是一种用于管理和重用线程的技术&#xff08;池化技术&#xff09;&#xff0c;它主…

Python爬虫追踪新闻事件发展进程及舆论反映

目录 实现方案 1. 确定目标新闻源&#xff1a; 2. 确定关键词&#xff1a; 3. 使用网络爬虫获取新闻内容&#xff1a; 4. 提取和分析新闻文章&#xff1a; 5. 追踪新闻事件的发展进程&#xff1a; 6. 监测舆论反映&#xff1a; 7. 数据可视化&#xff1a; 完整代码示例…

【DEVOPS】Jenkins使用问题 - 控制台输出乱码

0. 目录 1. 问题描述2. 解决方案3. 最终效果4. 总结 1. 问题描述 部门内部对于Jenkins的使用采取的是Master Slave Work Node的方式&#xff0c;即作为Master节点的Jenkins只负责任务调度&#xff0c;具体的操作由对应的Slave Work Node去执行。 最近团队成员反馈一个问题&a…

基于 OV5640 摄像头理论知识讲解-成像和采样原理

基于OV2640/ OV5640 的图像采集显示系统系列文章目录&#xff1a; &#xff08;1&#xff09;基于 OV5640 摄像头理论知识讲解-成像和采样原理 &#xff08;2&#xff09;基于 OV5640 摄像头理论知识讲解-数字接口和控制接口 &#xff08;3&#xff09;基于 OV5640 摄像头理论知…

未来科技城携手加速科技 共建集成电路测试公共服务平台!

8月26日&#xff0c;2023未来产业发展大会在杭州未来科技城国际会议中心开幕&#xff01;会上&#xff0c;发布了未来科技城培育发展未来产业行动计划&#xff0c;启动了未来产业发展共同体&#xff0c;进行了未来产业公共服务平台签约仪式。未来科技城与加速科技签约共建集成电…

系列十三、idea创建文件自动生成作者信息

File>Settings>Editor>File and Code Templates>Includes>File Header /*** Author : 一叶浮萍归大海* Date: ${DATE} ${TIME}* Description: */

24 WEB漏洞-文件上传之WAF绕过及安全修复

目录 WAF绕过上传参数名解析:明确哪些东西能修改?常见绕过方法&#xff1a;符号变异-防匹配( " ;)数据截断-防匹配(%00 ; 换行)重复数据-防匹配(参数多次)搜索引擎搜索fuzz web字典文件上传安全修复方案 WAF绕过 safedog BT(宝塔) XXX云盾 宝塔过滤的比安全狗厉害一些&a…

Django(9)-表单处理

django支持使用类创建表单实例 polls/forms.py from django import forms class NameForm(forms.Form):your_nameforms.CharField(label"Your name",max_length100)这个类创建了一个属性&#xff0c;定义了一个文本域&#xff0c;和它的label和最大长度。 polls/vi…

云服务器(Centos7系统)配置JAVA+mysql+tomcat 环境

文章主要内容来源云服务器&#xff08;Centos7系统&#xff09;部署javaweb项目&#xff08;二&#xff09;配置JAVAmysqltomcat 环境_man_zuo的博客-CSDN博客 模仿途中遇到的问题 连接无效 有时连接无法下载&#xff0c;可能是过期了&#xff0c;将其更换为官网给的下载连接即…

Java11(集合)

集合 1.集合框架 用于存储数量不等的多个对象&#xff0c;还可用于保存具有映射关系的关联数组 Java集合可分为Collection和Map两种体系 Collection接口 Set:元素无序&#xff0c;不可重复的集合----&#xff08;类似数学中的集合&#xff09; List:元素有序&#xff0c;可重…