【MYSQL】事务隔离级别以及InnerDB底层实现

news2024/11/15 22:53:53

事务隔离级别

读未提交(Read Uncommitted)

允许事务读取其他事务未提交的数据,可能会导致脏读。

读已提交(Read Committed)

一个事务只能看见已经提交的事务所做的更改,可以避免脏读,但可能会遇到不可重复读。

可重复读(Repeatable Read)

在一个事务内,多次读取同一数据的结果是一致的,即使其他事务在这期间对数据进行了修改和提交。此隔离级别可以防止不可重复读,但可能遇到幻读。

串行化(Serializable)

最高隔离级别,通过完全序列化事务来避免所有并发问题,这通常通过锁定事务访问的行来实现,性能开销较大。

在这里插入图片描述

MVCC的具体实现

隐藏字段

InnoDB存储引擎在每行数据的后面添加了三个隐藏字段:

1、DB_TRX_ID(6字节):记录创建或最后一次更新该行的事务ID。

在InnoDB中,每个事务都有一个唯一的事务ID,叫做transaction
id(缩写trx_id),它是在事务开始时候向InnoDB的事务系统申请的,并且按照申请顺序严格递增。在这里DB_TRX_ID就表示最近一次对该行数据作修改(insert或update)的事务ID。至于delete操作,InnoDB认为是一个update操作,不过会更新一个另外的删除位,将行表示为deleted,并非真正删除。

2、DB_ROLL_PTR(7字节):回滚指针,指向当前记录行的undo log信息,用于回滚该行的旧版本

3、DB_ROW_ID(6字节):行标识,如果表没有显式的主键或唯一索引时使用。这个字段和MVCC关系不大,所以我们在这里不必关注。

这是随着新行插入而单调递增的行ID。理解:当表没有主键或唯一非空索引时,InnoDB就会使用这个行ID自动产生聚簇索引。如果表有主键或唯一非空索引,聚簇索引就不会包含这个行ID了。

Read View(一致性视图)

read view的真正作用是用来做可见性判断的,里面保存了“对本事务不可见的其他活跃事务”。

按照可重复读的定义,一个事务启动的时候,能够看到所有已经提交的事务结果。但是之后,这个事务执行期间,其他事务的更新对它不可见。因此,一个事务只需要在启动的时候声明说,“以我启动的时刻为准,如果一个数据版本是在我启动之前生成的,就认;如果是我启动以后才生成的,我就不认,我必须要找到它的上一个版本”。当然,如果“上一个版本”也不可见,那就得继续往前找。

Read View有4个重要的字段

1、m_ids :创建 Read View 时,当前数据库中「活跃事务(启动了但没提交)」的事务 id 列表,注意是一个列表。
2、min_trx_id :创建 Read View 时,当前数据库中「活跃事务」中事务 id 最小的事务,也就是 m_ids 的最小值。
3、max_trx_id :不是 m_ids 的最大值,而是创建 Read View 时当前数据库中应该给下一个事务的 id 值,也就是全局事务中最大的事务 id 值 + 1;
4、creator_trx_id :指的是创建该 Read View 的事务的事务 id。

在这里插入图片描述
在可见性的实现上,InnoDB为每个事务构建了一个数组,用来保存这个事务启动瞬间,当前正在”活跃“的所有事务ID。”活跃“指的是启动了但还没提交。

数组里面事务 ID 的最小值记为低水位,当前系统里面已经创建过的事务 ID 的最大值加 1 记为高水位。这个视图数组和高水位,就组成了当前事务的一致性视图(read-view)。这里需要注意:低水位到高水位之间的某些事务ID是没在数组中的,没在的原因是它们已经提交了,比如低水位为100,高水位为106,而数组中可能只有100、101、103、105这四个事务ID,104和102不在的原因是因为在当前事务启动时,这两个事务已经提交了。

![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/08fb5599b2f74ecea93f2893b603cacd.png在这里插入图片描述
这样,对于当前事务的启动瞬间来讲,一个数据的DB_TRX_ID,存在以下几种可能:

1、如果落在绿色部分,表示这个版本是已提交的事务或者是当前事务自己生成的,这个数据是可见的;
2、如果落在红色部分,表示这个版本是由将来启动的事务生成的,是肯定不可见的;(需要去undo log找可见版本)
3、如果落在黄色部分,那就包括两种情况:
a. 如果DB_TRX_ID在数组中(也就说明这个事务在当前事务启动时还活跃),那么表示这个这个版本是由还没提交的事务生成的,不可见;(需要去undo log找可见版本)
b. 若 row trx_id 不在数组中,表示这个版本是已经提交了的事务生成的,可见。

读提交和可重复读的read view产生区别:

在innodb中的可重复读级别, 只有事务在begin之后,执行第一条select(读操作)时, 才会创建一个快照(read view),将当前系统中活跃的其他事务记录起来;并且事务之后都是使用的这个快照,不会重新创建,直到事务结束。
在innodb中的读提交级别, 事务在begin之后,执行每条select(读操作)语句时,快照会被重置,即会重新创建一个快照(read view)。

undo log

undo log中存储的是老版本数据,当一个事务需要读取记录行时,如果当前记录行不可见,可以顺着undo log链找到满足其可见性条件的记录行版本,这也是InnoDB利用”所有数据都有多个版本“这个特性,来实现可见性的核心。

下图记录了一行数据被多个事务连续更新后的状态(图中的row trx_id就是上面提到的DB_TRX_ID):

在这里插入图片描述

图中虚线框内是同一行数据的四个版本,当前最新版本是 V4,k 的值是 22,它是被 事务ID 为 25 的事务更新的,因此它的 DB_TRX_ID 是 25。

在上图中,三个虚线箭头其实就代表了undo log;V1、V2、V3其实并不是物理上真实存在的,而是每次需要的时候根据当前版本和undo log计算出来的,比如,需要V2的时候,就是通过V4依次执行U3、U2计算出来。

比如,假如有一个事务的低水位是18,它要读取上面图中的数据,那么当它访问时候,获取了当前的DB_TRX_ID为25,假设这个25在数组中(说明这个25在事务启动时依然活跃),那么因为25高于低水位,所以对于当前事务来说不可见,于是这个事务就会从V4通过U3计算得出V3,V3的DB_TRX_ID=17小于18,所以这个数据是可见的,所以对于当前事务来讲,这个事务的值通过undo log就可以构造出来,为11。

大多数对数据的变更操作包含insert/update/delete,在InnoDB里,undo log分为如下两类:

insert undo log:事务insert新记录时产生的undo log,只在事务回滚时需要,并且在事务提交后就可以立即丢弃
update undo log:事务对记录进行delete和update操作时产生的undo log,不仅在事务回滚时需要,快照读也需要,只有当数据库所使用的快照不涉及该日志记录,对应的回滚日志才会被purge线程删除。

Purge线程: 为了实现InnoDB的MVCC机制,更新或者删除操作都只是设置一下旧记录的deleted_bit,并不真正将旧记录删除。
为了节省磁盘空间,InnoDB有专门的purge线程来清理deleted_bit为true的记录。purge线程自己也维护了一个read
view,如果某个记录的deleted_bit为true,并且DB_TRX_ID相对于purge线程的read
view可见,那么这条记录一定是可以被安全清除的。

在MySQL InnoDB引擎中,各隔离级别是如何实现的呢?

读未提交(Read Uncommitted)

InnoDB实际上并不直接支持此隔离级别,因为这会引发脏读、不可重复读和幻读等问题。如果要实现的话,数据库可允许事务读取其他事务尚未提交的数据,不做任何额外的并发控制即可。

读已提交(Read Committed)

InnoDB通过多版本并发控制(MVCC)机制实现。在读已提交的隔离级别下,每个事务在每次读取数据时都会生成一个自己的读视图(Read View)。这个视图是由事务开始时正在提交的事务所影响的数据项的快照构成的。

具体实现上,MySQL会在每行数据后添加3个隐藏的列来实现MVCC,这3个列分别是:
1、DB_TRX_ID:记录创建或最后一次更新该行的事务ID。
2、DB_ROLL_PTR:指向回滚段的指针,用于回滚该行的旧版本。
3、DB_ROW_ID:行标识,如果表没有显式的主键或唯一索引时使用。这个字段和MVCC关系不大,所以我们在这里不必关注。

当事务需要读取数据时,它会读取DB_TRX_ID不为当前事务ID的行,即已提交事务的数据。
在这里插入图片描述

可重复读(Repeatable Read)

这是InnoDB默认的隔离级别,InnoDB也是通过MVCC机制来实现可重复读隔离级别的。可重复读隔离级别是启动事务时生成一个 Read View,然后整个事务期间都在用这个 Read View。

MVCC机制为每个事务分配一个唯一的事务ID,并记录每行数据的创建版本号和删除版本号,确保在同一个事务内多次读取同一数据时结果一致,解决了不可重复读的问题。MVCC通过数据行的隐藏列(例如事务ID、回滚指针等)以及undo日志来管理多个事务对同一数据的并发访问,确保事务看到的数据在事务期间保持一致,即便其他事务已经修改或删除了这些数据。

MVCC通过维护数据的多个版本来实现事务的隔离性,而无需依赖传统的锁机制(虽然InnoDB也使用锁,但主要是为了解决写冲突)。每个事务看到的数据是由该事务的开始时间点决定的,这保证了在可重复读级别下,即使其他事务提交了新的数据,当前事务仍然能够看到它开始时的数据状态,避免了脏读、不可重复读的问题,但幻读仍可能在某些场景下发生,除非使用了Next-Key Locks或者将隔离级别调整为串行化。

选择该隔离级别是因为主从同步如果先后读取不一致,可能会出现主从同步问题。

串行化(Serializable)

虽然InnoDB支持串行化隔离级别,但实际应用中较少使用,因为它通过完全锁定读取的行来防止并发修改,这会严重影响系统的并发性能。在串行化级别下,InnoDB会对涉及的行加锁,“写”会加“写锁”,“读”会加“读锁”。当出现读写锁冲突的时候,后访问的事务必须等前一个事务执行完成,阻止其他事务并发修改,以此实现最高的隔离性。

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

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

相关文章

基于CLIP特征的多模态大模型中的视觉短板问题

【论文极速读】 基于CLIP特征的多模态大模型中的视觉短板问题 FesianXu 20240706 at Tencent WeChat search team 前言 今天读到篇CVPR 24’的论文 [1],讨论了常见的多模态大模型(大多都基于CLIP语义特征,以下简称为MLLM)中的视觉…

阿里云服务器配置、搭建(针对Spring boot和MySQL项目)

这是一篇极其详细且痛苦的文章,还是在两位后端的大佬手把手教导下、以及我找遍全网所有资料、问了N遍AI、甚至直接申请阿里云工单一对一询问客服一整天、连续清空再上传反复30多次整个项目jar包......总结出来的终极要人命踩坑的问题总结 一、首先购买服务器 其实不…

Apache Seata分布式事务及其三种模式详解

本文来自 Apache Seata官方文档,欢迎访问官网,查看更多深度文章。 本文来自 Apache Seata官方文档,欢迎访问官网,查看更多深度文章。 Apache Seata分布式事务及其三种模式详解 分布式事务 Seata 及其三种模式详解 | Meetup#3 回顾…

基于TCP的在线词典系统(分阶段实现)

1.功能说明 一共四个功能: 注册 登录 查询单词 查询历史记录 单词和解释保存在文件中,单词和解释只占一行, 一行最多300个字节,单词和解释之间至少有一个空格。 2.功能演示 3、分阶段完成各个功能 3.1 完成服务器和客户端的连接 servic…

【深度学习】图形模型基础(5):线性回归模型第四部分:预测与贝叶斯推断

1.引言 贝叶斯推断超越了传统估计方法,它包含三个关键步骤:结合数据和模型形成后验分布,通过模拟传播不确定性,以及利用先验分布整合额外信息。本文将通过实际案例阐释这些步骤,展示它们在预测和推断中的挑战和应用。…

编程上下文Context及其实现原理

编程上下文Context及其实现原理 author:shengfq date:2024-07-06 title:编程上下文Context及其实现原理 category:编程思想1.编程中的上下文Context是指什么? 在编程和软件工程领域,“上下文”(Context)是一个多义词,其含义可以…

产品经理-​合作的6类干系人(8)

在一个项目中,产品经理并不是一个人在战斗,而是在很多同事的配合下共同完成项目。那产品经理到底要和哪些角色配合,一起完成项目呢 中间的产品经理是一个项目的驱动者。而产品经理的前方是“Boss/Leader”,也就是创业团队中公司的…

地级市数字经济指数、互联网用户数、数字金融普惠指数

2000-2022年地级市数字经济指数(含控制变量) 目录 数字经济如何改善环境污染 一、引言 二、文献综述 三、实证模型 四、数据来源 五、程序代码 六、运行结果 数字经济如何改善环境污染 摘要: 本论文旨在探讨数字经济对环境污染的改善作…

三级_网络技术_04_中小型网络系统总体规划与设计

1.下列关于路由器技术特征的描述中,正确的是()。 吞吐量是指路由器的路由表容量 背板能力决定了路由器的吞吐量 语音、视频业务对延时抖动要求较低 突发处理能力是以最小帧间隔值来衡量的 2.下列关于路由器技术特征的描述中,正确的是()。 路由器的…

Matlab中collectPlaneWave函数的应用

查看文档如下: 可以看出最多5个参数,分别是阵列对象,信号幅度,入射角度,信号频率,光速。 在下面的代码中,我们先创建一个3阵元的阵列,位置为:(-1,0,0&#x…

JavaWeb----JSPJSTL

目录 JSP显隐注释在JSP中写java程序JSP的指令标签JSP中的四大域对象简易版用户登录EL表达式 JSTL条件动作标签if标签 choose\when\otherwise标签迭代标签格式化动作标签 用户登录实例查看是否安装了mysql用户登录界面后台实现 JSP JSP全名是Java Server Pages,它是建…

【后端面试题】【中间件】【NoSQL】MongoDB查询优化3(拆分、嵌入文档,操作系统)

拆分大文档 很常见的一种优化手段,在一些特定的业务场景中,会有一些很大的文档,这些文档有很多字段,而且有一些特定的字段还特别的大。可以考虑拆分这些文档 大文档对MongoDB的性能影响还是很大的,就我个人经验而言&…

常见算法和Lambda

常见算法和Lambda 文章目录 常见算法和Lambda常见算法查找算法基本查找(顺序查找)二分查找/折半查找插值查找斐波那契查找分块查找扩展的分块查找(无规律的数据) 常见排序算法冒泡排序选择排序插入排序快速排序递归快速排序 Array…

在Apache HTTP服务器上配置 TLS加密

安装mod_ssl软件包 [rootlocalhost conf.d]# dnf install mod_ssl -y此时查看监听端口多了一个443端口 自己构造证书 [rootlocalhost conf.d]# cd /etc/pki/tls/certs/ [rootlocalhost certs]# openssl genrsa > jiami.key [rootlocalhost certs]# openssl req -utf8 -n…

Pycharm远程连接GPU(内容:下载安装Pycharm、GPU租借、配置SSH、将代码同步到镜像、命令行操控远程镜像、配置远程GPU解释器)

目录 windows下载安装pycharmGPU租借网站AutoDlfeaturize好易智算 GPU租借GPU选择选择镜像充值 然后创建镜像创建成功 复制SSH登录信息 远程进入镜像 在Pycharm中进行ssh连接新建SFTP配置SSH复制ssh根据复制的信息填写ssh配置测试连接 将代码同步到远程镜像上设置mappings将本地…

React 省市查询组件完整代码

目录 一、地区文件 二、Antd配合使用 三、实现效果 一、地区文件 下载地址:全国省市区数据_JSON格式_SQL格式 export const chinaArea {0: {1: 北京,2: 天津,3: 河北省,4: 山西省,5: 内蒙古自治区,6: 辽宁省,7: 吉林省,8: 黑龙江省,9: 上海,10: 江苏省,11: 浙…

计算机出现找不到msvcp140.dll无法继续执行代码怎么办?推荐7个有效解决方法

在日常使用电脑过程中会经常遇到各式各样的问题,比如msvcp140.dll丢失或找不到msvcp140.dll文件是最常见的问题之一,那么遇到这个问题要怎么解决呢?msvcp140.dll到底是什么?为什么会出现msvcp140.dll丢失问题?今天给大…

原生事件监听及组件内置事件处理

监听事件 我们可以使用 v-on 指令 (简写为 ) 来监听 DOM 事件,并在事件触发时执行对应的 JavaScript。用法:v-on:click“handler” 或 click“handler”。 事件处理器 (handler) 的值可以是: 内联事件处理器:事件被触发时执行的…

《QT从基础到进阶·四十三》QPlugin插件多线程问题和只有插件dll没有头文件和lib文件时调用插件中的方法

1、插件和多线程问题: 创建插件对象不能放到多线程执行,不然报错:ASSERT failure in QWidget: "Widgets must be created in the GUlthread. //不能放在多线程执行 QPluginLoader pluginLoader(pluginsDir.absoluteFilePath(fileName))…

单选多选提交问卷,代码示例

element中 需要对接口返回的数据进行分析。多选问题使用checkbox,单选题使用radio。 多选时可以绑定min/ma&am…