MVCC多版本并发控制相关面试题整理

多版本并发控制是一种用于支持并发事务的数据库管理系统技术,它允许多个事务同时访问数据库,而不会相互干扰或导致数据不一致。MVCC通过在数据库中维护不同版本的数据来实现这一目标,从而允许每个事务看到一致的数据库快照。

并发导致的问题

数据库并发是指在同一时间内,多个事务同时对数据库进行读取和写入操作的能力。以下是三种常见的数据库并发场景:

  1. 读-读并发: 多个事务同时对数据库进行读取操作,彼此之间不涉及写入操作。
  2. 读-写并发: 多个事务同时进行读取和写入操作,存在线程安全问题,会产生脏读、不可重复读、幻读。
  3. 写-写并发: 多个事务同时进行写入操作,可能涉及操作同一条数据,导致数据丢失,事物 1 事物 2 同时更新一条记录时,事物 1 提交,事物 2 也提交,事物 1 回滚后导致覆盖掉了事物 2 的更新。

最早的数据库系统,只有读读之间可以并发,读写,写读,写写都要阻塞。引入多版本之后,只有写写之间相互阻塞(MySQL 自动对涉及的数据行加上即排他锁),其他三种操作都可以并行,这样大幅度提高了InnoDB的并发度。

实现 MVCC

InnoDB 会向数据库中的每行记录增加三个字段:
DB_ROW_ID:隐藏的自增 ID(主键),6字节,如果有主键,则不会包含该列,如果没有主键,会根据DB_ROW_ID 产生一个聚餐索引。
DB_TRX_ID:事务ID,6字节,记录插入或 最后一次更新这条记录的事务 ID,MySQL InnoDB 里面每个事务都会有一个唯一事务 ID,它在事务开始的时候会跟 InnoDB 的事务系统申请的,并且严格按照顺序递增的。
DB_ROLL_PTR:回滚指针,7字节,指向上个版本数据在 undo log 里的位置。

版本链

新 insert 的数据没有 undo log,**DB_ROLL_PTR **字段为空。 当要 update 数据的时候,会先创建 undo log,以及指向该 undo log 的回滚指针 roll_ptr,并且会将 roll_ptr 更新到 **DB_ROLL_PTR **字段中,更新数据的 DB_TRX_ID 属性为当前的事务 ID 。当某条数据被多次修改时,该数据会存在多个版本,通过 DB_ROLL_PTR 链接形成一个类似版本链的概念。
演示文稿1.jpg

当前读和快照读

当前读(Current Read): 当前读是一种读取操作,事务在执行读取时会读取数据库的当前状态,包括其他事务已经提交的变更。当前读允许事务读取最新的实时数据,但也可能受到其他并发事务的影响,可能发生不可重复读等问题。常见的 update/insert/delete、还有 select … for update、select … lock in share mode 都是当前读。
快照读(Snapshot Read): 快照读是一种读取操作,事务在执行读取时会获得一个数据库的快照或一个特定时间点的数据视图。也就是 MVCC 生成的 ReadView。在整个事务执行期间,这个数据视图保持一致,即事务看到的是事务开始时数据库的快照,不受其他事务的影响。用于普通的 select 的语句。

一致性视图(ReadView)

当隔离级别为 RR 时:每开启一个事务,数据库系统会给这个事务分配一个事务 ID,这个 ID 是自增的,所以事物 ID 越大事物越新,当这个事务执行 select 语句的时候,会生成一个当前时间点的事务快照读视图ReadView, ReadView 包含几个属性:
m_ids
创建当前 ReadView 时,系统活跃事务 id 升序的列表,即还未提交的事物 id 列表。
m_low_limit_id (不可见范围的最小(low)id
创建当前 ReadView 时,将要分给下一个事物的 id,也就是当前系统最大事务版本号+1。
m_up_limit_id(可见范围的最大(up)id
创建当前ReadView 时,系统正处于活跃事务最小版本号
m_creator_trx_id
创建当前ReadView的事务 id
代码位置: mysql-8.1.0\storage\innobase\read\read0read.cc
image.png
image.png

可见性判断

当某个事务执行快照读的时候,会创建一个 ReadView 读视图,并且用这个 ReadView 判断当前事务能够看到哪个版本的数据。可能是当前最新的数据,也有可能是该行数据的 undo log(版本链) 里面的某个版本的数据。一个事务启动后,判断某个版本的数据能否被该事务访问,判断流程如下:
1、 如果被访问版本的 DB_TRX_ID 与 该事务创建的 ReadView 中的 m_creator_trx_id 值相同,说明就是当前这个事务在访问它自己修改过的数据。
2、 如果被访问版本的 DB_TRX_ID < ReadView 中的 m_up_limit_id(低水位),表明被访问版本的事务在当前事务生成 ReadView 前已经提交,所以该版本可以被当前事务访问。
3、 如果被访问版本的 DB_TRX_ID >= ReadView 中的 m_low_limit_id(高水位),表明被访问版本的事务在当前事务生成 ReadView 后才开启,所以该版本不可以被当前事务访问。
4、 m_low_limit_id > DB_TRX_ID >= m_up_limit_id <= 之间,这种情况就说明这个数据有可能是在当前事务开始的时候还没有提交的,可以分情况判断:

  • 如果 DB_TRX_ID 不在 m_ids 列表中,说明创建 ReadView 时生成该版本的事务已经被提交,该版本可以被访问。
  • 如果 DB_TRX_ID 在 m_ids 中,则说明read view产生的时候数据还没有提交,但是如果 DB_TRX_ID == creator_trx_id ,那么说明这个数据就是当前事务自己生成的,该版本可以被访问。
  • 如果 DB_TRX_ID 在m_ids 中,且 DB_TRX_ID 不等于creator_trx_id那就说明read view产生的时候数据还没有提交,又不是自己生成的,所以这种情况下,该版本不能被访问。

以上三种情况是通过二分法进行查找判断的。
5、如果该版本的条件都不满足ReadView 的条件时,则通过当前版本的 DB_ROLL_PTR 找到上一个版本,再来和ReadView 条件匹配,直到找到一条满足条件的历史数据,找不到则返回空结果。

RC/RR级别快照读

RC/RR 级别生成 ReadView 的时机是不同的:

  • RR 级别下的某个事务对某条记录进行的第一次 select 会创建一个快照 Read View,此后在调用快照读的时候,使用的还是同一个ReadView,所以只要当前事务在其他事务提交更新之前使用过快照读,那么之后的快照读使用的都是同一个Read View,所以对之后的修改不可见.
  • RC 级别下事务中每次 select 都会生成一个快照和 ReadView,这就是我们在 RC 级别下的事务中可以看到别的事务提交更新的原因。

总之在 RC 隔离级别下,每次快照读都会生成最新的 ReadView;而在 RR 级别下,则是同一个事务中的第一个快照读才会创建ReadView,之后的快照读获取的都是同一个 ReadView。所以说 RR 在 RC 的基础上通过生成 Read View 的时机不同从而解决了不可重复读的问题。

数据删除和purge 线程

而对于删除,其实就是一种特殊的更新,InnoDB 在 info_bits 中用一个标记位 delete_flag 标识是否删除,并不真正将过时的记录删除。当我们在进行判断时,会检查下 delete_flag 是否被标记,如果是,会有专门的 purge 线程来清理。

什么是记录锁,什么是间隙锁?什么是 Next-Key Locks?

记录锁、间隙锁(也称为范围锁)、以及临键锁是三种不同类型的锁,用于管理并发事务的访问,InnoDB 的锁是加上在索引上的。

  1. 记录锁(Record Locks)

这种锁直接应用在数据库表中的记录(行)上。当一个事务请求对某一行的记录进行写操作时,系统可能会给该记录加上记录锁,防止其他事务同时修改同一行。这确保了在给定时间只有一个事务能够修改该记录,从而维护数据的一致性。

  1. 间隙锁(Gap Locks)

间隙锁锁定的是两个记录之间的间隙,左开右开的区间。这主要用于防止其他事务在间隙中插入新的记录,从而确保范围查询的一致性,其它事务在这个间隙做删除操作也会被锁阻塞的。如果一个事务执行范围查询操作并使用了间隙锁,它将锁定查询范围内的所有记录以及这些记录之间的空隙,防止其他事务在这个范围内插入新的记录。间隙锁是可重复读RR隔离级别下特有的。
比如语句select * from user where age>1 and age<10 for update,将会锁住age在(1,10)的范围区间,此时其他事务对该区间的操作都会被阻塞

  1. 临键锁(Next-Key Locks

是通过算法将记录锁间隙锁组合, 锁住的是左开右闭的区间。

MVCC 解决幻读了吗?

快照读(普通 select 语句)的时候,是通过 MVCC 方式解决了幻读,因为可重复读隔离级别下,在执行第一个查询语句后,会创建一个 Read View,后续的查询语句利用这个 Read View,通过这个 Read View 就可以在 undo log 版本链找到事务开始时的数据,所以事务过程中每次查询的数据都是一样的,即使中途有其他事务插入了新纪录,是查询不出来这条数据的,所以就很好了避免幻读问题。
当前读(select … lock in share mode、select … for update、insert、 update、 delete 等语句)时,这些语句执行前都会查询最新版本的数据,是通过 Next-Key Locks(记录锁+间隙锁,只在)方式解决了幻读,因为当执行这些语句的时候,会自动加上 Next-Key Locks,如果有其他事务在 Next-Key Locks 锁范围内插入了一条记录,那么这个插入语句就会被阻塞,无法成功插入,所以就很好了避免幻读问题。
如果事务中都使用快照读,那么就不会产生幻读现象;但是如果快照读和当前读混用,就会产生幻读。

临键锁一定解决了幻读问题吗?

按照 MySQL 官方的说法,即使在可重复读的情况下,幻读仍然是可能的。官方说法https://bugs.mysql.com/bug.php?id=63870,所以有更高的隔离级别出现。

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

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

相关文章

【数据结构】树与二叉树(廿二):树和森林的遍历——后根遍历(递归算法PostOrder、非递归算法NPO)

文章目录 5.1 树的基本概念5.1.1 树的定义5.1.2 森林的定义5.1.3 树的术语 5.2 二叉树5.3 树5.3.1 树的存储结构1. 理论基础2. 典型实例3. Father链接结构4. 儿子链表链接结构5. 左儿子右兄弟链接结构 5.3.2 获取结点的算法5.3.3 树和森林的遍历1. 先根遍历&#xff08;递归、非…

qt5.15.2及6.0以上版本安装

文章目录 下载在线安装器安装打开软件 下载在线安装器 因为从qt5.15开始不支持离线下载安装了&#xff0c;只能通过在线安装的方式进行安装。 下载在线安装下载器&#xff1a; 这个在线安装下载器网上也都是可以找到。 这里是其放到网盘上的下载地址&#xff1a; 链接&#x…

DL Homework 8

目录 习题5-2 证明宽卷积具有交换性&#xff0c; 即公式(5.13)&#xff0e; 习题5-4 对于一个输入为100 100 256的特征映射组&#xff0c; 使用3 3的卷积核&#xff0c; 输出为100 100 256的特征映射组的卷积层&#xff0c; 求其时间和空间复杂度&#xff0e; 如果引入一…

Openwrt linux 启动流程

OpenWRT 启动流程 内核启动过程&#xff1a;【/init/mian.c】 Uboot --> start_kernel() --> rest_init() --> kernel_thread(kernel_init) --> kernel_init_freeable() 初始化过程&#xff1a; Linux Kernel(kernel_init) --> /etc/preinit --> /sbin/in…

2023 年最新百度智能云千帆大模型 Node.Js 本地测试 / 微信机器人详细教程

千帆大模型概述 一站式企业级大模型平台&#xff0c;提供先进的生成式AI生产及应用全流程开发工具链。直接调用ERNIE-Bot 4.0及其他主流大模型&#xff0c;并提供可视化开发工具链&#xff0c;支持数据闭环管理、专属大模型定制、大模型训练调优、插件编排等功能。 千帆大模型…

Python基础:字符串详解(需补充完善)

1. 字符串定义 在Python中&#xff0c;字符串是一种数据类型&#xff0c;用于表示文本数据。字符串是由字符组成的序列&#xff0c;可以包含字母、数字、符号和空格等字符。在Python中&#xff0c;你可以使用单引号&#xff08;&#xff09;或双引号&#xff08;"&#x…

阅读笔记——《Removing RLHF Protections in GPT-4 via Fine-Tuning》

【参考文献】Zhan Q, Fang R, Bindu R, et al. Removing RLHF Protections in GPT-4 via Fine-Tuning[J]. arXiv preprint arXiv:2311.05553, 2023.【注】本文仅为作者个人学习笔记&#xff0c;如有冒犯&#xff0c;请联系作者删除。 目录 摘要 一、介绍 二、背景 三、方法…

输出后,我悟了!

大家好&#xff0c;我是木川 今天和前同事吃饭聊天&#xff0c;谈到了输出&#xff0c;今天简单谈下关于输出的重要性 一、为什么要输出 1、不输出容易忘&#xff0c;如果不输出很容易就忘记了&#xff0c;如果再遇见一次&#xff0c;还是需要重新学习&#xff0c;实际上是浪费…

有关HarmonyOS-ArkTS的Http通信请求

一、Http简介 HTTP&#xff08;Hypertext Transfer Protocol&#xff09;是一种用于在Web应用程序之间进行通信的协议&#xff0c;通过运输层的TCP协议建立连接、传输数据。Http通信数据以报文的形式进行传输。Http的一次事务包括一个请求和一个响应。 Http通信是基于客户端-服…

【Linux学习笔记】protobuf 基本数据编码

https://zhuanlan.zhihu.com/p/557457644https://zhuanlan.zhihu.com/p/557457644 [新文导读] 从Base64到Protobuf&#xff0c;详解Protobuf的数据编码原理本篇将从Base64再到Base128编码&#xff0c;带你一起从底层来理解Protobuf的数据编码原理。本文结构总体与 Protobuf 官…

软件学院PTA天梯赛初赛选拔赛题解

目录 7-2 生肖确定&#xff08;模拟&#xff09; AC代码&#xff1a; 7-3 韩信点兵&#xff08;模拟&#xff09; AC代码&#xff1a; 7-4 程序员买包子&#xff08;模拟&#xff09; AC代码&#xff1a; 7-5 h0078. 蛇形矩阵变形 AC代码&#xff1a; 7-6 军事体能成绩…

23.11.26日总结

图片与文字顶部对齐&#xff1a; <div class"addDishImgBox"><span class"addDishImgZi">商品图片&#xff1a;</span><img :src"myStorePhoto" class"addDishImg"> </div> .addDishImgBox{display: f…

8.前端--CSS-文本属性【2023.11.26】

CSS Text&#xff08;文本&#xff09;属性可定义文本的外观&#xff0c;比如文本的颜色、对齐文本、修饰文本、文本缩进、行间距等 1.文本颜色 color 属性用于定义文本的颜色。 语法&#xff1a; div { color: red; }属性&#xff1a; 2.文本对齐 text-align 属性用于设置元…

学生党福音!一个能自定义词库的单词软件--单词魔方

大家好 我是Yhen 这一期给大家介绍一款自制的单词软件–单词魔方 文章目录 一.创作缘由二.功能介绍&升级内容三.使用方法四.程序获取 一.创作缘由 为什么会有想法开发这个单词软件呢&#xff1f; 因为平时自己在做阅读&#xff0c;看电影时积累下来了一些单词 当我想要系…

【Linux】Linux项目自动化构建工具 --- make / makefile

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前正在学习c和Linux还有算法 ✈️专栏&#xff1a;Linux &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章有啥瑕疵&#xff0c;希望大佬指点一二 …

Node.js下载安装及配置镜像源

一、进入官网地址下载安装包 https://nodejs.org/dist 选择对应你系统的Node.js版本 这里我选择的是Windows系统、64位 二、安装程序 &#xff08;1&#xff09;下载完成后&#xff0c;双击安装包&#xff0c;开始安装Node.js (2)直接点【Next】按钮&#xff0c;此处可根据…

jmeter 接口测试快速入门 以飞致云平台为例

飞致云电商API地址系统来自飞致云项目。接口API地址&#xff1a;https://gz.fit2cloud.com/swagger-ui.html 飞致云电商系统接口文档 V1.0&#xff1a;见 有道云笔记 该网站可以做接口测试练习。快速了解如何测试接口&#xff0c;如何做关联 系统基地址&#xff1a;https://g…

树套树 (线段树+splay)

树套树&#xff0c;就是线段树、平衡树、树状数组等数据结构的嵌套。 最简单的是线段树套set&#xff0c;可以解决一些比较简单的问题&#xff0c;而且代码根线段树是一样的只是一些细节不太一样。 本题中用的是线段树套splay&#xff0c;代码较长。 树套树中的splay和单一的…

【数据结构】堆(C语言)

今天我们来学习堆&#xff0c;它也是二叉树的一种&#xff08;我滴神树&#xff01;&#xff09; 目录 堆的介绍&#xff1a;堆的代码实现&#xff1a;堆的结构体创建&#xff1a;堆的初始化&#xff1a;堆的销毁&#xff1a;堆的push&#xff1a;堆的pop&#xff1a;判空 &am…

力扣373场周赛题解

第一题&#xff1a; 这个题是一个简单题&#xff0c;数据范围也特别小&#xff0c;所以直接使用模拟方式暴力解答。 直接进行行移动的过程&#xff0c;然后检查移动后的结果是否与移动前相同。 代码&#xff1a; ​ public class Solution {// 将指定行循环右移k次pri…