【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及实现原理

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

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

相关文章

电视盒子哪个好?2024口碑网络电视盒子排行榜

多年来电视盒子始终占据重要地位,功能上并没有受到影响。在这么多品牌中哪些电视盒子的评价是最好的呢?小编根据各大电商平台的用户评价情况整理了口碑最好的网络电视盒子排行榜,跟着小编一起看看市面上的电视盒子哪个好吧。 TOP 1&#xff1…

如何访问远程MySQL数据库?

远程访问MySQL数据库是在不同设备之间实现数据交互的一种方式。通过远程访问,用户可以轻松地操作远程MySQL数据库,从而实现数据的读写、修改和查询等操作。本文将介绍远程访问MySQL数据库的原理和实现方法,以及一种被广泛应用的解决方案【天联…

[入门到放弃]设计模式-笔记

模块化设计 20240448 模块不包含数据,通过实例的指针,实现对实例的操作;唯一包含的数据是用于管理这些模块的侵入式链表模块只负责更具定义的数据结构,执行对应的逻辑,实现不同实例的功能; 参考资料 使用…

TCP/IP协议—UDP

TCP/IP协议—UDP UDP协议UDP通信特点 UDP头部报文UDP检验 UDP协议 用户数据传输协议 (UDP,User Datagram Protocol) 是一种无连接的协议,提供了简单的数据传输服务,不保证数据的顺序以及完整性。应用层很多通信协议都基于UDP进行传输&#x…

[当人工智能遇上安全] 13.威胁情报实体识别 (3)利用keras构建CNN-BiLSTM-ATT-CRF实体识别模型

《当人工智能遇上安全》系列将详细介绍人工智能与安全相关的论文、实践,并分享各种案例,涉及恶意代码检测、恶意请求识别、入侵检测、对抗样本等等。只想更好地帮助初学者,更加成体系的分享新知识。该系列文章会更加聚焦,更加学术…

最新常见的图数据库对比,选型,架构,性能对比

图数据库排名 地址:https://db-engines.com/en/ranking/graphdbms 知识图谱查询语言 SPARQL、Cypher、Gremlin、PGQL 和 G-CORE 语法 / 语义 / 特性SPARQLCypherGremlinPGQLG-CORE图模式匹配查询语法CGPCGPCGP(无可选)1CGPCGP语义子图同态、包 2无重复边、包 2子…

大唐极简史

唐朝(618年-907年),是中国历史上一个强盛的朝代,以其疆域辽阔、政治稳重、经济繁荣、文化繁荣而著称。唐朝的开国皇帝是李渊,他建立了一个强大的中央集权政府,使得唐朝成为当时世界上最繁荣的国家之一。 唐…

vmware虚拟机补救

更新了虚拟机里面工具和资料,进行了磁盘整理和压缩,虚拟机运行进不去系统了。 网站找的修复方法均不可行。补救措施:利用DiskGenius.exe(要用高版本不然复制的时候就知道了) DG1342.rar - 蓝奏云 加载虚拟硬盘 2008x…

最新微信支付商家转账到零钱各场景怎样开通?

商家转账到零钱是什么? 商家转账到零钱是企业付款到零钱的升级版,它的功能是,如果系统需要对用户支付费用,比如发放佣金、提成、退款等,可以直接转账到用户的微信零钱。这个功能在 2022 年 5 月 18 日之前叫做企业付款…

2024年MathorCup数模竞赛B题问题一二三+部分代码分享

inputFolderPath E:\oracle\images\; outputFolderPath E:\oracle\process\; % 获取文件夹中所有图片的文件列表 imageFiles dir(fullfile(inputFolderPath, *.jpg)); % 设置colorbar范围阈值 threshold 120; % 遍历每个图片文件 for i 1:length(imageFiles) % 读…

个人网站制作 Part 18 提升用户体验:添加页面404错误处理 | Web开发项目

文章目录 👩‍💻 基础Web开发练手项目系列:个人网站制作🚀 添加404错误处理页面🔨创建404错误处理页面🔧步骤 1: 在项目根目录创建404错误处理页面🔧步骤 2: 添加404错误处理页面内容 &#x1f…

数据结构复习指导之绪论(数据结构的基本概念)

文章目录 绪论: 考纲内容 知识框架 复习提示 1.数据结构的基本概念 1.1基本概念和术语 1.数据 2.数据元素 3.数据对象 4.数据类型 5.数据结构 1.2数据结构三要素 1.数据的逻辑结构 2.数据的存储结构 3.数据的运算 绪论: 考纲内容 算法时…

计算机网络----第十天

配置vlan 广播风暴的含义: 含义:设备发出的广播帧在广播域中传播,占用网络带宽,降低设备性能 隔离广播的方式: 方式:用路由器来隔离广播 用VLN隔离广播 vlan的定义: 定义:虚拟…

13-pyspark的共享变量用法总结

目录 前言广播变量广播变量的作用 广播变量的使用方式 累加器累加器的作用累加器的优缺点累加器的使用方式 PySpark实战笔记系列第四篇 10-用PySpark建立第一个Spark RDD(PySpark实战笔记系列第一篇)11-pyspark的RDD的变换与动作算子总结(PySpark实战笔记系列第二篇))12-pysp…

海外媒体宣发:这7个旅游业媒体套餐击中宣传痛点-华媒舍

旅游业如何有效宣传自身成为了一个重要的问题。众多旅游企业却面临着宣传痛点,即无法将优质内容传达给目标受众。近期,出现了7个旅游业媒体套餐,它们被称为解决宣传痛点的突破性方案。本文将介绍这7个旅游业媒体套餐,并说明它们为…

一篇实操vitrualbox虚拟机根目录扩容(详细,实操陈功)

一篇实操vitrualbox虚拟机根目录扩容(详细,实操陈功) 创建虚拟介质 第一步、 第二步、 第三步、一直下一步,直到下面的页面 分配空间到更目录下 第一步、 第二步、查看创建的物理磁盘 lsblk第三步、查看原本磁盘可用空间 df …

掌握现代 C++:Lambda 在 C++14、C++17 和 C++20 中的演变

深入研究Lambda 在 C14、C17 和 C20 中的演变 一、背景二、C14 中的 Lambda2.1、默认参数2.2、模板参数2.3、广义捕获2.4、从函数返回 lambda 三、C17 中的 Lambda四、C20 中的 Lambda总结 一、背景 Lambda 是现代 C 最受欢迎的功能之一。自从在 C 11 中引入以来,它…

Day 23 669. 修剪二叉搜索树 108.将有序数组转换为二叉搜索树 538.把二叉搜索树转换为累加树 总结篇

修剪二叉搜索树 给定一个二叉搜索树,同时给定最小边界L 和最大边界 R。通过修剪二叉搜索树,使得所有节点的值在[L, R]中 (R>L) 。你可能需要改变树的根节点,所以结果应当返回修剪好的二叉搜索树的新的根节点。 ​ 最直接的想法&#xff0…

【CSS】SVG图片属性及修改颜色

最近的开发中遇到了SVG不能修改颜色的问题,以前是直接用,没有研究过,现在搞个笔记记录下 SVG的属性: width:设置最终SVG图片的宽度height:设置最终SVG图片的高度viewbox:视区,在svg上截取一块&#xff0c…

【C++学习】C++智能指针:提高代码安全与性能的利器

文章标题 智能指针的提出智能指针概念及使用RAII 智能指针的原理C库多种智能指针详解版本一:std::auto_ptr(C98)1. std::auto_ptr 使用2. std::auto_ptr 原理3. std::auto_ptr 模拟实现 版本二:unique_ptr (C11)1. unique_ptr 的使…