SQL进阶理论篇(十二):InnoDB中的MVCC是如何实现的?
文章目录
- 简介
- 事务版本号
- 行记录的隐藏列
- Undo Log
- Read View的工作流程
- 总结
- 参考文献
简介
在不同的DBMS里,MVCC的实现机制是不同的。本节我们会以InnoDB举例,讲解InnoDB里MVCC的实现机制。
我们需要掌握这么几个概念:
- 事务版本号
- 行记录的隐藏列
- Undo Log
- Read View
事务版本号
什么是事务版本号?
每开启一个事务,我们就会从数据库中获得一个事务ID,这个ID就是事务的版本号。它是自增长的,通过这个ID,我们就可以判断不同事务的时间顺序。
行记录的隐藏列
什么是行记录的隐藏列?
InnoDB的叶子段里存储了数据页,数据页中保存了行记录,而在行记录里有一些比较重要的隐藏字段。
如图:
db_row_id:隐藏的行ID,用来生成默认的聚集索引。如果我们在创建数据表的时候没有指定聚集索引,那么InnoDB就会使用这个隐藏的行ID来创建聚集索引。借以提升查找效率。
db_trx_id:操作这个数据的事务ID,其实就是最后一个对该数据进行插入或者更新的事务ID。
db_roll_ptr:回滚指针,指向这个记录的Undo Log信息。
Undo Log
什么是Undo Log
InnoDB把行记录快照保存在了Undo Log里。
如图所示:
由上图可见,回滚指针其实是将这个数据行的所有快照记录,通过链表结构串联了起来。每个快照记录都保有了操作的事务ID。
当想要找历史快照的时候,就遍历回滚指针查找即可。
Read View的工作流程
read view是如何工作的?
这个比较复杂。
首先它有什么作用,我们前面讲过,Undo Log里保存了很多历史快照,那么对一个事务来讲,它应该查询哪个历史快照呢?
这时候就需要用到Read View了,其解决了行的可见性问题。
一个事务在开启时,会创建属于自己的Read View,这里面保存了事务开启时所有活跃(还没有提交)的事务列表。换个角度理解,这里面保存的其实是不应该让当前事务看到的其他所有事务。(还没提交的事务的内容,原则上是不应该被别人看到的)
Read View里有几个重要的属性:
- trx_ids:其他活跃事务的ID集合;
- low_limit_id:trx_ids中最大的事务ID;
- up_limit_id:trx_ids中最小的事务ID;
- creator_trx_id:创建这个Read View的事务ID。
如图所示,下面是一个trx_ids集合,其中最大事务为trx8,最小事务是trx2,当前事务是creator_trx_id。
如果当前事务想要读取某一行记录,而这一行记录保存的最后修改事务ID是trx_id_line,那么有这么几种情况:
如果trx_id_line < up_limit_id,即当前最小活跃事务,就说明在这些活跃事务创建之前,这个行记录就已经被提交了,那么这个行记录对该事务,应该是可见的。
如果trx_id_line > low_limit_id,说明该行记录在这些活跃的事务创建之后才创建,这个行记录对当前事务应该不可见。
如果 up_limit_id < trx_id_line < low_limit_id,说明trx_id_line 这个事务,可能在当前事务创建的时候,还处于活跃状态,所以我们可以去trx_ids里去遍历。如果找到的话,说明这个事务还没提交,那么这条记录应该不可见,没找到的话,说明事务已经提交了,该行记录可见。
原理简单的说,就是在creator_trx_id这个事务创建的时候,如果trx_id_line这个事务是活跃的,那么它对应的行记录是不可见的;如果不是活跃的,那么对应的行记录就是可见的。这个其实就是避免脏读的概念。只不过是通过事务ID大小比较的方式来实现的。
最后,我们串一串完整的流程,当查询一条记录的时候,系统到底是如何通过多版本并发控制技术来找到它的:
- 获取当前事务自己的版本号,即事务ID;
- 获取自己的Read View;
- 查询得到的行记录数据,与Read View中的活跃事务版本号进行比较;
- 如果行记录符合Read View的规则,即行记录对当前事务可见,那就直接读这条行记录;如果行记录不符合Read View的规则,即行记录对当前事务不可见(原因见上),那就去Undo Log里获取该行记录符合情况的历史快照;
- 最后返回符合规则的数据。
因此,在InnoDB中,MVCC是通过Undo Log + Read View来进行数据读取,Undo Log保存了数据的历史快照,而Read View帮助我们判断当前最新版本的数据是否可见,不可见,那就去Undo Log里取历史。
总结
MVCC是通过乐观锁思想,来保证事务的隔离。
MVCC 的核心就是 Undo Log+ Read View,“MV”就是通过 Undo Log 来保存数据的历史版本,实现多版本的管理,“CC”是通过 Read View 来实现管理,通过 Read View 原则来决定数据是否显示。
需要注意,针对不同的隔离级别,Read View 的生成策略不同。或者说,根据Read View的生成策略不同,MVCC得以实现不同的隔离级别。
当隔离级别是读已提交时,一个事务中,每次select查询都会获取一次Read View,如果每次获取到的Read View不同,就会产生不可重复读或者幻读的情况。
当隔离级别是可重复读的时候,一个事务只在第一次select 的时候获取一次Read View,之后的select都是对这个Read View的复用(解决了不可重复读的问题)。同时,在可重复读的隔离级别下,InnoDB会采用MVCC + Next-Key锁的机制来避免幻读问题。
那当隔离级别是读未提交时,就不合适用MVCC来控制了。因为根本就不需要用版本控制了,大家都直接读最新的行记录就可以了。
InnoDB中有三种行级锁:
- 记录锁:对单个行记录添加锁;
- 间隙锁(Gap Locking):锁住一个范围,但不包括记录本身。采用间隙锁可以防止幻读的产生(应该是锁住范围,不让范围增加或者减少,但是对记录的update应该还是可以的,估计防止不了不可重复读)。
- Next-Key锁:锁住一个范围,同时锁定范围本身,相当于是间隙锁+记录锁。
在读已提交的情况下,InnoDB采用的是记录锁;在可重复读的隔离级别下,InnoDB会采用Next-Key锁的机制。
参考文献
- 31丨为什么大部分RDBMS都会支持MVCC?
相关文章:

SQL进阶理论篇(十二):InnoDB中的MVCC是如何实现的?
文章目录 简介事务版本号行记录的隐藏列Undo LogRead View的工作流程总结参考文献 简介 在不同的DBMS里,MVCC的实现机制是不同的。本节我们会以InnoDB举例,讲解InnoDB里MVCC的实现机制。 我们需要掌握这么几个概念: 事务版本号行记录的隐藏…...

SpringCloudAliBaba篇之Seata:分布式事务组件理论与实践
1、事务简介 事务(Transaction)是访问并可能更新数据库中各种数据项的一个程序执行单元(unit)。在关系数据库中,一个事务由一组SQL语句组成,事务具有4个属性:原子性、一致性、隔离性、持久性。这四个属性通常称为ACID原则。 原子性(atomici…...

在centos7.9上安装Jenkins的安装过程
1.jenkins的安装和配置: 安装JDK: yum install -y fontconfig java-11-openjdk # 安装目录:/usr/lib/jvm # fontconfig 是 Linux 系统中用于配置和管理字体的一种工具 下载jenkins安装包: sudo wget -O /etc/yum.repos.d/jenkins…...
uni-app基本标签
导航栏设置 - navigationBarBackgroundColor: 设置导航栏的背景颜色(全局页面) - navigationBarTextStyle: 导航栏标题颜色(仅支持 black 和 white) - navigationBarTitleText: 设置导航栏标题内容 - enablePullDownRefresh: 是否…...

《PySpark大数据分析实战》-14.云服务模式Databricks介绍基本概念
📋 博主简介 💖 作者简介:大家好,我是wux_labs。😜 热衷于各种主流技术,热爱数据科学、机器学习、云计算、人工智能。 通过了TiDB数据库专员(PCTA)、TiDB数据库专家(PCTP…...

微信小程序校园跑腿系统怎么做,如何做,要做多久
在这个互联网快速发展、信息爆炸的时代,人人都离不开手机,每个人都忙于各种各样的事情,大学生也一样,有忙于学习,忙于考研,忙着赚学分,忙于参加社团,当然也有忙于打游戏的&#x…...

当我分别问8款GPT一个问题。。。
前两天下班在地铁上无聊寻思问一下不同的GPT一个相同的问题,哪个会给出我比较满意的答案,然后我就提问:我老妹有点憨怎么办?(ps:开玩笑的,嘻嘻。。。) 很明显其他GPT都给出了大差不差…...
Elasticsearch 8.9 search命令执行查询源码
一、相关的API的handler1、接收HTTP请求的handler2、往数据节点发送查询请求的action(TransportSearchAction)3、通过transportService把查询请求发送到指定的数据节点 二、数据节点收到请求的处理逻辑1、尝试从缓存中加载查询结果2、不通过缓存查询,直接执行查询(1…...
【PHP】身份证正则验证、校验位验证
目录 1.正则 简单正则 详细正则 2.校验位验证 1.正则 简单正则 function isValidIdCardNumber($idCardNumber) {// 身份证号长度为 15 位或 18 位$pattern /^(?:\d{15}|\d{17}[\dxX])$/;return preg_match($pattern, $idCardNumber); }$idCardNumber 12345678901234567…...

Matlab示例-Examine 16-QAM Using MATLAB学习笔记
工作之余学习16-QAM 写在前面 网上看到许多示例,但一般都比较难以跑通。所以,还是老方法,先将matlab自带的例子研究下。 Examine 16-QAM Using MATLAB Examine 16-QAM Using MATLAB 或者,在matlab中,键入&#x…...
ArcGIS Pro SDK运行消息只提示一次
工具大部分都是异步执行,所以提示信息需要异步执行完再进行,所以注意async和await的使用。 相关async和await的文章请查看C# 彻底搞懂async/await_c# async await-CSDN博客 public async Task InformationPrompt() {string message String.Empty;await ArcGIS.De…...

通话状态监听-Android13
通话状态监听-Android13 1、Android Telephony 模块结构2、监听和广播获取通话状态2.1 注册2.2 通话状态通知2.3 通话状态 3、通知状态流程* 关键日志 frameworks/base/core/java/android/telephony/PhoneStateListener.java 1、Android Telephony 模块结构 Android Telephony…...

无懈可击的防泄密之旅:迅软DSE在民营银行的成功实践
客户简要介绍 某股份有限公司主体是中部地区的民营银行,由其母公司联合9家知名民营企业共同发起设立。正式开业于2016年,紧紧围绕目标产业生态圈和消费金融,着力打造产业银行、便捷银行、数字银行、财富管理银行为一体的BEST银行,…...

【送书活动】智能汽车、自动驾驶、车联网的发展趋势和关键技术
文章目录 前言01 《智能汽车》推荐语 02 《SoC底层软件低功耗系统设计与实现》推荐语 03 《SoC设计指南》推荐语 05 《智能汽车网络安全权威指南(上册)》推荐语 06 《智能汽车网络安全权威指南(下册)》推荐语 后记赠书活动 前言 …...

不同版本QT使用qmake时创建QML项目的区别
不同版本QT使用qmake时创建QML项目的区别 文章目录 不同版本QT使用qmake时创建QML项目的区别一、QT5新建QML项目1.1 目录结构1.2 .pro 文件内容1.3 main.cpp1.4 main.qml 二、QT6新建QML项目2.1 目录结构2.2 .pro文件内容2.3 main.cpp2.4 main.qml 三、两个版本使用资源文件的区…...

【PHP入门】1.1-PHP初步语法
-PHP语法初步- PHP是一种运行在服务器端的脚本语言,可以嵌入到HTML中。 1.1.1PHP代码标记 在PHP历史发展中,可以使用多种标记来区分PHP脚本 ASP标记: <% php代码 %>短标记: <? Php代码 ?>,以上两种…...

如何在jenkins容器中安装python+httprunner+pytest+git+allure(一)
背景: API接口自动化使用python语言实现,利用httprunner框架编写自动化用例场景(执行的时候还是依赖pytest),使用jenkins自动构建git上的源代码,并产生allure报告可视化展示API执行结果。 步骤 1.进入jenkins容器 注意使用roo…...
Android终端模拟器Termux上使用Ubuntu
Termux 上安装各种 Linux 系统是通过 proot-distro 工具来实现的,所以先安装一下 proot-distro 工具。 ~ $ pkg install proot-distro 查看Termux支持安装那些Linux ~ $ proot-distro listSupported distributions:* Alpine LinuxAlias: alpineInstalled: noComme…...

【神器】wakatime代码时间追踪工具
文章目录 wakatime简介支持的IDE安装步骤API文档插件费用写在最后 wakatime简介 wakatime就是一个IDE插件,一个代码时间追踪工具。可自动获取码编码时长和度量指标,以产生很多的coding图形报表。这些指标图形可以为开发者统计coding信息,比如…...

UML统一建模语言
一、建模语言的背景: 通俗地阐述就是:客户一开始不知道要什么,开发通过客户的阐述进行理解和分析,这个过程中间可能会产生一些误解。为了避免此类事件,所以需要建模。类似于要建造一栋楼,建筑设计师根据住…...
python如何将word的doc另存为docx
将 DOCX 文件另存为 DOCX 格式(Python 实现) 在 Python 中,你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是,.doc 是旧的 Word 格式,而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...

ServerTrust 并非唯一
NSURLAuthenticationMethodServerTrust 只是 authenticationMethod 的冰山一角 要理解 NSURLAuthenticationMethodServerTrust, 首先要明白它只是 authenticationMethod 的选项之一, 并非唯一 1 先厘清概念 点说明authenticationMethodURLAuthenticationChallenge.protectionS…...

C# 类和继承(抽象类)
抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...

智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制
在数字化浪潮席卷全球的今天,数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具,在大规模数据获取中发挥着关键作用。然而,传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时,常出现数据质…...
Android第十三次面试总结(四大 组件基础)
Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成,用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机: onCreate() 调用时机:Activity 首次创建时调用。…...

Unity VR/MR开发-VR开发与传统3D开发的差异
视频讲解链接:【XR马斯维】VR/MR开发与传统3D开发的差异【UnityVR/MR开发教程--入门】_哔哩哔哩_bilibili...

内窥镜检查中基于提示的息肉分割|文献速递-深度学习医疗AI最新文献
Title 题目 Prompt-based polyp segmentation during endoscopy 内窥镜检查中基于提示的息肉分割 01 文献速递介绍 以下是对这段英文内容的中文翻译: ### 胃肠道癌症的发病率呈上升趋势,且有年轻化倾向(Bray等人,2018&#x…...

数据分析六部曲?
引言 上一章我们说到了数据分析六部曲,何谓六部曲呢? 其实啊,数据分析没那么难,只要掌握了下面这六个步骤,也就是数据分析六部曲,就算你是个啥都不懂的小白,也能慢慢上手做数据分析啦。 第一…...

如何把工业通信协议转换成http websocket
1.现状 工业通信协议多数工作在边缘设备上,比如:PLC、IOT盒子等。上层业务系统需要根据不同的工业协议做对应开发,当设备上用的是modbus从站时,采集设备数据需要开发modbus主站;当设备上用的是西门子PN协议时…...
LUA+Reids实现库存秒杀预扣减 记录流水 以及自己的思考
目录 lua脚本 记录流水 记录流水的作用 流水什么时候删除 我们在做库存扣减的时候,显示基于Lua脚本和Redis实现的预扣减 这样可以在秒杀扣减的时候保证操作的原子性和高效性 lua脚本 // ... 已有代码 ...Overridepublic InventoryResponse decrease(Inventor…...