当前位置: 首页 > news >正文

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大小比较的方式来实现的。

最后,我们串一串完整的流程,当查询一条记录的时候,系统到底是如何通过多版本并发控制技术来找到它的:

  1. 获取当前事务自己的版本号,即事务ID;
  2. 获取自己的Read View;
  3. 查询得到的行记录数据,与Read View中的活跃事务版本号进行比较;
  4. 如果行记录符合Read View的规则,即行记录对当前事务可见,那就直接读这条行记录;如果行记录不符合Read View的规则,即行记录对当前事务不可见(原因见上),那就去Undo Log里获取该行记录符合情况的历史快照;
  5. 最后返回符合规则的数据。

因此,在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锁的机制。

参考文献

  1. 31丨为什么大部分RDBMS都会支持MVCC?

相关文章:

SQL进阶理论篇(十二):InnoDB中的MVCC是如何实现的?

文章目录 简介事务版本号行记录的隐藏列Undo LogRead View的工作流程总结参考文献 简介 在不同的DBMS里&#xff0c;MVCC的实现机制是不同的。本节我们会以InnoDB举例&#xff0c;讲解InnoDB里MVCC的实现机制。 我们需要掌握这么几个概念&#xff1a; 事务版本号行记录的隐藏…...

SpringCloudAliBaba篇之Seata:分布式事务组件理论与实践

1、事务简介 事务(Transaction)是访问并可能更新数据库中各种数据项的一个程序执行单元(unit)。在关系数据库中&#xff0c;一个事务由一组SQL语句组成&#xff0c;事务具有4个属性&#xff1a;原子性、一致性、隔离性、持久性。这四个属性通常称为ACID原则。 原子性(atomici…...

在centos7.9上安装Jenkins的安装过程

1.jenkins的安装和配置&#xff1a; 安装JDK&#xff1a; yum install -y fontconfig java-11-openjdk # 安装目录&#xff1a;/usr/lib/jvm # fontconfig 是 Linux 系统中用于配置和管理字体的一种工具 下载jenkins安装包&#xff1a; sudo wget -O /etc/yum.repos.d/jenkins…...

uni-app基本标签

导航栏设置 - navigationBarBackgroundColor: 设置导航栏的背景颜色&#xff08;全局页面&#xff09; - navigationBarTextStyle: 导航栏标题颜色&#xff08;仅支持 black 和 white&#xff09; - navigationBarTitleText: 设置导航栏标题内容 - enablePullDownRefresh: 是否…...

《PySpark大数据分析实战》-14.云服务模式Databricks介绍基本概念

&#x1f4cb; 博主简介 &#x1f496; 作者简介&#xff1a;大家好&#xff0c;我是wux_labs。&#x1f61c; 热衷于各种主流技术&#xff0c;热爱数据科学、机器学习、云计算、人工智能。 通过了TiDB数据库专员&#xff08;PCTA&#xff09;、TiDB数据库专家&#xff08;PCTP…...

微信小程序校园跑腿系统怎么做,如何做,要做多久

​ 在这个互联网快速发展、信息爆炸的时代&#xff0c;人人都离不开手机&#xff0c;每个人都忙于各种各样的事情&#xff0c;大学生也一样&#xff0c;有忙于学习&#xff0c;忙于考研&#xff0c;忙着赚学分&#xff0c;忙于参加社团&#xff0c;当然也有忙于打游戏的&#x…...

当我分别问8款GPT一个问题。。。

前两天下班在地铁上无聊寻思问一下不同的GPT一个相同的问题&#xff0c;哪个会给出我比较满意的答案&#xff0c;然后我就提问&#xff1a;我老妹有点憨怎么办&#xff1f;&#xff08;ps&#xff1a;开玩笑的&#xff0c;嘻嘻。。。&#xff09; 很明显其他GPT都给出了大差不差…...

Elasticsearch 8.9 search命令执行查询源码

一、相关的API的handler1、接收HTTP请求的handler2、往数据节点发送查询请求的action(TransportSearchAction)3、通过transportService把查询请求发送到指定的数据节点 二、数据节点收到请求的处理逻辑1、尝试从缓存中加载查询结果2、不通过缓存查询&#xff0c;直接执行查询(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 写在前面 网上看到许多示例&#xff0c;但一般都比较难以跑通。所以&#xff0c;还是老方法&#xff0c;先将matlab自带的例子研究下。 Examine 16-QAM Using MATLAB Examine 16-QAM Using MATLAB 或者&#xff0c;在matlab中&#xff0c;键入&#x…...

ArcGIS Pro SDK运行消息只提示一次

工具大部分都是异步执行&#xff0c;所以提示信息需要异步执行完再进行,所以注意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在民营银行的成功实践

客户简要介绍 某股份有限公司主体是中部地区的民营银行&#xff0c;由其母公司联合9家知名民营企业共同发起设立。正式开业于2016年&#xff0c;紧紧围绕目标产业生态圈和消费金融&#xff0c;着力打造产业银行、便捷银行、数字银行、财富管理银行为一体的BEST银行&#xff0c…...

【送书活动】智能汽车、自动驾驶、车联网的发展趋势和关键技术

文章目录 前言01 《智能汽车》推荐语 02 《SoC底层软件低功耗系统设计与实现》推荐语 03 《SoC设计指南》推荐语 05 《智能汽车网络安全权威指南&#xff08;上册&#xff09;》推荐语 06 《智能汽车网络安全权威指南&#xff08;下册&#xff09;》推荐语 后记赠书活动 前言 …...

不同版本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是一种运行在服务器端的脚本语言&#xff0c;可以嵌入到HTML中。 1.1.1PHP代码标记 在PHP历史发展中&#xff0c;可以使用多种标记来区分PHP脚本 ASP标记&#xff1a; <% php代码 %>短标记&#xff1a; <? Php代码 ?>&#xff0c;以上两种…...

如何在jenkins容器中安装python+httprunner+pytest+git+allure(一)

背景&#xff1a; API接口自动化使用python语言实现&#xff0c;利用httprunner框架编写自动化用例场景&#xff08;执行的时候还是依赖pytest),使用jenkins自动构建git上的源代码&#xff0c;并产生allure报告可视化展示API执行结果。 步骤 1.进入jenkins容器 注意使用roo…...

Android终端模拟器Termux上使用Ubuntu

Termux 上安装各种 Linux 系统是通过 proot-distro 工具来实现的&#xff0c;所以先安装一下 proot-distro 工具。 ~ $ pkg install proot-distro 查看Termux支持安装那些Linux ~ $ proot-distro listSupported distributions:* Alpine LinuxAlias: alpineInstalled: noComme…...

【神器】wakatime代码时间追踪工具

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

UML统一建模语言

一、建模语言的背景&#xff1a; 通俗地阐述就是&#xff1a;客户一开始不知道要什么&#xff0c;开发通过客户的阐述进行理解和分析&#xff0c;这个过程中间可能会产生一些误解。为了避免此类事件&#xff0c;所以需要建模。类似于要建造一栋楼&#xff0c;建筑设计师根据住…...

Linux命令行控制小米电源开关

飞灵科技产品 flyelf-tech.com&#xff0c;flyelf.taobao.com 最近有需求通过命令控制局域网内小米电源开关&#xff0c;以便于写脚本对产品进行反复上电的启动测试。参考了这篇文章&#xff1a;https://blog.csdn.net/2301_77209380/article/details/129797846 获取小米设备的…...

docker nginx 部署静态网站

1、dockerfile FROM nginx AS baseWORKDIR /appEXPOSE 80COPY . /app2、dockercompose.yaml version: 3 services:adminservice:container_name: adminwebbuild:context: ./dockerfile: Dockerfileports:- "5000:80"labels:description: adminwebrestart: always3、…...

uniapp之屏幕右侧出现滚动条去掉、隐藏、删除【好用!】

目录 问题解决大佬地址最后 问题 解决 在最外层view上加上class“content”;输入以下样式。注意&#xff1a;两个都必须存在在生效。 .content {/* 跟屏幕高度一样高,不管view中有没有内容,都撑开屏幕高的高度 */height: 100vh; overflow: auto; } .content::-webkit-scrollb…...

Linux 系统开机启动流程

可能没有完全理解&#xff0c;后期整理完Linux的内容&#xff0c;应该理解会深入一些&#xff0c;试着用更简洁的方式和图形来记录&#xff0c;以及一些概念的完善 2023-12-14 一、开机流程 BIOS MBR/GPT 加载 BIOS 的硬件信息与进行自检&#xff0c;并依据设定取得第一个可…...

vue2源码解析---watch和computed

监听属性watch 监听属性介绍 我们可以使用 watch 函数在每次响应式状态发生变化时触发回调函数wach 可以用于异步任务 监听属性的初始化 watch和computed都先走initSate判断传入选项 export function initState(vm) {const opts vm.$options; // 获取所有的选项if (opts.…...

【云原生】华为云踩坑日志(更新于2023.12.10)

1、华为云建议我们把sfs容量型升级到turbo版本&#xff0c;但是CCE产品storageclass sfs-turbo共享存储卷不支持动态绑定&#xff0c;官网文档可以实现动态创建子目录&#xff0c;建议大家直接选择这个&#xff0c;不要踩坑了 2、CCE 涉及到的产品&#xff0c;有的需要查看产品…...

计算机网络:自顶向下第八版学习指南笔记和课后实验--网络层(控制平面)

网络层&#xff1a;控制平面 记录一些学习计算机网络:自顶向下的学习笔记和心得 Github地址&#xff0c;欢迎star ⭐️⭐️⭐️⭐️⭐️ 控制平面作为一种网络范围的逻辑&#xff0c;不仅控制沿着从源主机到目的主机的端到端路径间的路由器如何转发数据报&#xff0c;而且控制…...

MFC 窗口创建过程与消息处理

目录 钩子简介 代码编写 窗口创建过程分析 消息处理 钩子简介 介绍几个钩子函数&#xff0c;因为它们与窗口创建工程有关 安装钩子函数 HHOOK SetWindowsHookExA([in] int idHook,[in] HOOKPROC lpfn,[in] HINSTANCE hmod,[in] DWORD dwThreadId ); 参数说明…...

基于JavaWeb+SSM+Vue微信小程序的移动学习平台系统的设计和实现

基于JavaWebSSMVue微信小程序的移动学习平台系统的设计和实现 源码获取入口Lun文目录前言主要技术系统设计功能截图订阅经典源码专栏Java项目精品实战案例《500套》 源码获取 源码获取入口 Lun文目录 第1章 绪论 1 1.1 课题背景 1 1.2 课题意义 1 1.3 研究内容 2 第2章 开发环…...

解决docker alpine /bin/sh: ./main: not found

解决docker alpine /bin/sh: ./main: not found golang中编译之后的二进制文件部署在alpine镜像中出现了not found问题解决这种情况是因为动态链接库位置错误导致的&#xff0c;alpine镜像使用的是musl libc而不是gun libc。因而动态链接库的位置不一致。在基础镜像内执行&…...