【MVCC】深入浅出彻底理解MVCC

MVCC概述

MVCC(Multi-Version Concurrency Control)即多版本并发控制。主要是为了提高数据库的并发性能而提供的,采用了不加锁的方式处理读-写并发冲突,确保了任何时刻的读操作都是非阻塞的。只需要很小的开销,就可以实现非锁定读,从而大大提高数据库系统的并发性能。所以我们也可以说MVCC是一种用来解决读-写冲突的无锁并发控制

引入

假设我发表了一篇博客,检查的时候发现了有几个错字,打算去修改,修改完之后要重写发布并审核。那此时对其他正在看文章的读者来说,他们是不是看不到了呢,答案是否定的,他们依然能够看到,不过看到的还是有错别字的版本,即旧版本。当审核通过之后就用新版本去覆盖了旧版#本,此时看到的文章就是已经修改过的新版本。

MVCC多版本并发控制

而对于InnoDB的MVCC机制来说,思路也大致相同。并发读写是存在线程安全问题的,有可能出现脏读、幻读、不可重复读。而MVCC的读其实是快照读,快照读读取到的数据不一定是最新的,又可能是历史的版本。也即让并发的事务的读写操作作用于不同的版本,比如读老版本,写新版本,这样无论执行写操作的事务干了啥都不会影响读的事务。
需要注意的是MVCC只在RCRR两个隔离级别下工作。如果是RU的话,允许脏读的存在,即一个事务可以读取到另一个事务未提交的数据,自然可以读到最新的版本,与MVCC冲突。如果是SERIALIZABLE,所有的事务都是串行的,不存在并发,因此也就没有MVCC什么事了。虽然MVCC在RCRR下工作,但是他们的实现方式又是不同的。

实现原理

MVCC主要是通过隐藏字段Undo-log日志以及ReadView来实现的。

隐藏字段

数据库表中的每一行除了我们显示定义的几个字段之外,还构建了一些InnoDB引擎的隐藏字段,主要的有DB_ROW_IDDB_Deleted_BitDB_TRX_IDDB_ROLL_PTR

  • DB_ROW_ID:隐藏主键,6Bytes。InnoDB存储引擎是按照主键作为聚簇索引列来构建B+树存储的,如果表中没有主键,那么就选择一个唯一非空的字段。如果两种都没有就InnoDB会自动以DB_ROW_ID产生一个聚簇索引,只不过这个索引在上层无法使用,仅提供给InnoDB构建树结构存储表数据。
  • DB_Deleted_Bit:删除标识,1Bytes。这里不做过多赘述。
  • DB_TRX_ID:最近修改/插入事务ID,6Bytes。MySQL对于每一个创建的事务,都会为其分配一个事务ID,事务ID同样遵循顺序递增的特性,即后来的事务ID绝对会比之前的ID要大。但是对于select查询语句,其事务id=0。如果是手动开启的事务,无论是否是select,MySQL都会为其分配事务ID。而TRX_ID记录的就是最近一次改动当前这条数据的事务ID。
  • DB_ROLL_PTR:回滚指针,7Bytes。指向这条记录的上一个版本(存储于 rollback segment 里)。当一个事务对一条数据做了改动后,都会将旧版本的数据放到Undo-log日志中,而DB_ROLL_PTR就是一个地址指针,指向Undo-log日志中旧版本的数据,当需要回滚事务时,就可以通过这个隐藏列,来找到改动之前的旧版本数据,而MVCC机制也利用这点,实现了行数据的多版本。

Undo-log

在InnoDB中undo日志一共有两种类型,分别是Update Undo LogInsert Undo Log

  • Update Undo Log:这种类型的Undo日志主要用来存储更新数据之前的原始信息,其主要目标是满足在事务执行过程中的数据修改引发的回滚操作;并用于在读取数据时,保证数据的一致性。
  • Insert Undo Log:在插入操作中产生的日志。只在事务回滚时需要,InnoDB并不需要保存完整的行数据信息,它主要用于标记这条新插入的记录在事务完成之前对其他事务是不可见的。
    假设有一个person表,表中存储的数据如下:
    ![[Pasted image 20240411134955.png]]

执行这样两个事务:

start transaction;
update person set user_name = "李四" where u_id = 1;
commit;
start transaction;
update person set sex = "女" where u_id = 2;
commit;

其实就会出现这样一条版本链,旧版本的信息存储在undo日志中,新的输入的db_roll_ptr指向的只上一个版本的地址。
![[Pasted image 20240411140059.png]]

值得注意的是,新版本数据都会插入到链表头中,而不是追加到链表尾部。

update的执行过程

  1. 对ID=1这条要修改的行数据加上排他锁
  2. 将原本的旧数据拷贝到Undo-log的rollback Segment区域。
  3. 对表数据上的记录进行修改,修改完成后将隐藏字段中的trx_id改为当前事务ID。
  4. 将隐藏字段中的roll_ptr指向Undo-log中对应的旧数据,并在提交事务后释放锁。

Undo-log日志要设计出版本链,一方面可以实现事务回滚,另一方面则可以实现MVCC机制

ReadView

如果t2事务要查询一条行数据,此时这条数据正在被他t1事务修写,那么这条行数据也就可能存在多个旧版本数据,t2在查询的时候,应该查询哪个旧版本的数据呢?此时就需要ReadView。具体来说,当一个事务需要读取数据时,InnoDB会创建一个ReadView实例,为该事务提供一个数据的“快照”,在这个快照中记录着当前所有活跃事务的ID(活跃事务是指还在执行的事务,即未结束(提交/回滚)的事务)。

当一个事务启动后,首次执行select操作时,MVCC就会生成一个数据库当前的ReadView,通常而言,一个事务与一个ReadView属于一对一的关系(不同隔离级别下也会存在细微差异),ReadView一般包含四个核心内容:

  • creator_trx_id:当前创建这个ReadView的事务id
  • trx_ids:在生成当前的ReadView之前,系统内活跃的事务id列表
  • up_limit_id:活跃的当前事务列表中,最小的事务id
  • low_limit_id:生成当前ReadView时,系统要给下一个任务分配的事务id。

看一个ReadView示意图:
![[Pasted image 20240411165934.png]]

假设当前数据库中有t1~t5这5个事务,其中活跃着的事务时t1,t2,t4,t3几经回滚,t5已经提交,此时有一条select语句执行时,就会生成一个ReadView,没有开启事务进行select,而是直接select,那么就会为其分配trx_id=0。所以产生快照的信息是:

{"creator_trx_id" : "0","trx_ids" : "[1,2,4]","up_limit_id" : "1","low_limit_id" : "6"
}

MVCC机制的实现原理

当一个事务尝试修改某条数据时,会将表中的旧数据放入udno日志中;当一个事务查询某条数据的时候,MVCC会生成一个ReadView快照读。其中Undo-log主要实现数据的多版本,ReadView则主要实现多版本的并发控制。

执行过程

  1. 当事务中出现select语句时,会生成一个ReadView
  2. 判断数据行中的隐藏列trx_idReadView.creator_trx_id是否相等。
    • 相等:表示创建ReadView快照和修改行数据(修改行数据这个事务生成的就是trx_id)是同一个事务,那么这个事务自然可以读取到这行最新版本的数据。
    • 不相等:代表目前要查询的数据,是被其他事务修改过的,继续下面的判断
  3. 判断数据行中的隐藏列trx_idReadView.up_limit_id的大小关系。
    • 前者小于后者:表示修改行数据的这个事务,在创建快照前就已经完成,可以读取最新版本的数据。
    • 前者大于等于后者:代表改动行数据的事务还在执行,继续进行判断
  4. 判断数据行中的隐藏列trx_idReadView.low_limit_id这个值的大小关系。
    • 前者大于等于后者:那么表示这行数据是在创建ReadView(即,当前事务开始)之后被修改的,因此不能访问最新版数据。
    • 前者小于后者:表示改动行数据的事务ID在up_limit_id、low_limit_id之间,需要进一步判断。
  5. 继续判断trx_id是否在trx_ids中。
    • :表示改动行数据的事务目前依旧在执行,不能访问最新版数据。
    • 不在:表示改动行数据的事务已经结束,可以访问最新版的数据。

这一块我的整理还是比较抽象的,建议再去看看文件末尾的参考资料,再去理解和消化。

RC、RR下的MVCC

  • 在RC隔离级别下,是每个快照读都会生成并获取最新的ReadView;
  • 在RR隔离级别下,则是同一个事务中的第一个快照读才会创建ReadView, 之后的快照读获取的都是同一个ReadView。

参考资料

  • MySQL之MVCC机制:为什么你改了的数据我还看不见?
  • MVCC详解,深入浅出简单易懂
  • 【MySQL笔记】正确的理解MySQL的MVCC及实现原理

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

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

相关文章

ArcGIS Pro 3D建模简明教程

在本文中,我讲述了我最近一直在探索的在 ArcGIS Pro 中设计 3D 模型的过程。 我的目标是尽可能避免与其他软件交互(即使是专门用于 3D 建模的软件),并利用 Pro 可以提供的可能性。 这个短暂的旅程分为三个不同的阶段:…

信息系统项目管理师0048:审计内容(3信息系统治理—3.1 IT审计—3.2.4审计内容)

点击查看专栏目录 文章目录 3.2.4审计内容 3.2.4审计内容 IT审计业务和服务通常分为IT内部控制审计和IT专项审计。IT内部控制审计主要包括组织层面IT控制审计、IT一般控制审计及应用控制审计;IT专项审计主要是指根据当前面临的特殊风险或者需求开展的IT审计&#xf…

3、JVM对象的创建于内存分配原理

对象的创建 对象创建的主要流程: 1.类加载检查 虚拟机遇到一条new指令时,首先将去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已被加载、解析和初始化过。如果没有,那必须先执行相应的类加…

Go——Goroutine介绍

一. 并发介绍 进程和线程 进程是程序在操作系统中一次执行过程,系统进程资源分配和调度的一个独立单位。线程是进程执行的实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。一个进程可以创建和撤销多个线程&#xff0c…

【若依前后端分离】首页-多个按钮控制同一个图表

示例图&#xff1a;上面四个框可以点击 重要代码片段 &#xff1a; index_v1中 <panel-group handleSetLineChartData"handleSetLineChartData" :data"totalData"/> : 这是一个自定义的 Vue 组件。名称是 panel-group。handleSetLineChartData"…

WEB3.0:互联网的下一阶段

随着互联网的发展&#xff0c;WEB3.0时代正在逐步到来。本文将深入探讨WEB3.0的定义、特点、技术应用以及未来展望&#xff0c;为读者带来全新的思考。 一、什么是WEB3.0&#xff1f; WEB3.0可以被理解为互联网发展的下一阶段&#xff0c;是当前WEB2.0的升级版。相较于2.0时代…

有哪些软件可以限制应用安装呢?

在限制应用安装方面&#xff0c;有几种方法和工具可供选择&#xff0c;具体取决于你的需求和设备类型。以下是一些常见的方法和软件&#xff1a; 1. **家长控制功能**&#xff1a;操作系统如iOS、Android和Windows等都提供了家长控制功能&#xff0c;允许家长限制特定用户的应…

二进制形式与编码方式的概念略有不同

二进制形式和编码方式在文件处理中有着密切的联系&#xff0c;但它们表示的概念略有不同。 1. **二进制形式**&#xff1a;指的是数据在计算机中以二进制&#xff08;0和1&#xff09;的形式表示。在文件处理中&#xff0c;以二进制形式写入文件意味着将数据按照原始的二进制格…

【DM8】同义词

同义词就是别名 同义词可以通过掩盖一个&#xff08;表、视图、序列、函数、存储过程等对象&#xff09;的真实的名字和拥有者。 1、公共同义词&#xff1a;所有的用户可以使用&#xff0c;使用的时候不加模式名。 2、普通同义词&#xff1a;在某个模式下面定义的同义词&#x…

C#:求两个整数的最大值

任务描述 本关任务&#xff1a;编写一个程序&#xff0c;实现从键盘输入的两个整数&#xff0c;输出两个整数的最大值。 测试说明 平台会对你编写的代码进行测试&#xff1a; 测试输入&#xff1a; 4 91 预期输出&#xff1a; 最大值&#xff1a;91 测试输入&#xff1a; 15…

实时数据开发

笔者并没有专业的实时数仓的开发经验&#xff0c;只是从别人经验和网上资料综合整理而来&#xff0c;仅供参考。 实时数据开发步骤&#xff1a;1、需求分析&#xff1b;2、确定Source、Sink、Dim&#xff1b;3、任务创建&#xff1b;4、任务开发和修改&#xff1b;5、参数与资…

【go从入门到精通】作用域,包详解

作者简介&#xff1a; 高科&#xff0c;先后在 IBM PlatformComputing从事网格计算&#xff0c;淘米网&#xff0c;网易从事游戏服务器开发&#xff0c;拥有丰富的C&#xff0c;go等语言开发经验&#xff0c;mysql&#xff0c;mongo&#xff0c;redis等数据库&#xff0c;设计模…

性能分析-数据库(安装、索引、sql、执行过程)与磁盘知识(读、写、同时读写、内存速度测试)

数据库 数据库&#xff0c;其实是数据库管理系统dbms。 数据库管理系统&#xff0c; 常见&#xff1a; 关系型数据库&#xff1a; mysql、pg、 库的表&#xff0c;表与表之间有关联关系&#xff1b; 表二维表统一标准的SQL&#xff08;不局限于CRUD&#xff09;非关系型数据…

【Python】关于函数

1.调用时 当有重名的时候&#xff0c;使用最后声明的同名函数 解决函数命名冲突问题&#xff1a; ~ 模块名.函数名 ----> 使用函数的完全限定名 ~ 别名 ----> 在导入函数的时候&#xff0c;使用as关键字对其别名 2.参数 (1)函数的参数的说明&#xff1a; ~ /…

阿里云9元服务器租用收费价格表_免费云服务器领取

2024年最新阿里云服务器租用费用优惠价格表&#xff0c;轻量2核2G3M带宽轻量服务器一年61元&#xff0c;折合5元1个月&#xff0c;新老用户同享99元一年服务器&#xff0c;2核4G5M服务器ECS优惠价199元一年&#xff0c;2核4G4M轻量服务器165元一年&#xff0c;2核4G服务器30元3…

第P2周:CIFAR10彩色图片识别

第P2周&#xff1a;CIFAR10彩色图片识别 &#x1f368; 本文为&#x1f517;365 天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K 同学啊 &#x1f4cc;第P2周&#xff1a;彩色图片识别&#x1f4cc; 难度&#xff1a;小白入门⭐ 语言&#xff1a;Python…

QSFP-DD 和 QSFP+ / QSFP28 / QSFP56 / OSFP / CFP8 / COBO 之间的区别

&#x1f31f;QSFP-DD 作为400G 光模块的最小外形尺寸&#xff0c;提供业界最高的带宽密度&#xff0c;同时利用对低速 QSFP 可插拔模块和电缆的向后兼容性&#xff0c;使其在光纤制造商中很受欢迎。作为400G高速应用中最新的热门光收发器&#xff0c;QSFP-DD经常被拿来与QSFP5…

目标检测YOLO实战应用案例100讲-基于多特征融合的SSD目标检测(续)

目录 3 基于多感受野融合的目标检测算法 3.1基于多特征图的网络结构 3.2感受野与空洞卷积

单例模式(Singleton Pattern)在JAVA中的应用

在软件开发中&#xff0c;设计模式是解决特定问题的一种模板或者指南。它们是在多年的软件开发实践中总结出的有效方法。JAVA设计模式广泛应用于各种编程场景中&#xff0c;以提高代码的可读性、可维护性和扩展性。本文将介绍单例模式&#xff0c;这是一种常用的创建型设计模式…

计算机视觉——DiffYOLO 改进YOLO与扩散模型的抗噪声目标检测

概述 物体检测技术在图像处理和计算机视觉中发挥着重要作用。其中&#xff0c;YOLO 系列等型号因其高性能和高效率而备受关注。然而&#xff0c;在现实生活中&#xff0c;并非所有数据都是高质量的。在低质量数据集中&#xff0c;更难准确检测物体。为了解决这个问题&#xff…