MySQL(八):事务的隔离级别、MVCC的原理

news2024/11/17 6:35:17

目录

  • 一、事务的隔离级别
    • 1.1 事务的隔离性
    • 1.2 事务并发执行引发的一致性问题
      • 1.2.1 脏写
      • 1.2.2 脏读
      • 1.2.3 不可重复读
      • 1.2.4 幻读
    • 1.3 SQL标准中的四种隔离级别
    • 1.4 MySQL中支持的4中隔离级别
  • 二、MVCC原理
    • 2.1 版本链
    • 2.2 ReadView
    • 2.3 READ COMMITED 每次读取数据前都生成一个ReadView
    • 2.4 REPEATABLE 在第一次读取数据时生成一个ReadView
    • 2.5 MVCC小结

一、事务的隔离级别

1.1 事务的隔离性

MySQL是一个客户端/服务器架构的软件,对于一个服务器来说,可以有多个客户端与之连接,服务器可以同时处理来自多个客户端的多个事务。
当并发执行的多个事务访问相同的数据,就可能出现"事务一致性"问题,举例,A用户有11元,B用户有2元,A同时向B进行两次转账5元的操作,两次转账操作分别对应事务T1和T2,如果按照下列操作顺序执行,那么就可能引发事务一致性问题
在这里插入图片描述
那么如何保证事务的一致性呢?最简单粗暴的方式就是让事务之间串行执行,也就是让事务之间都隔离开,互不干涉,这就是事务的隔离性
但让事务完全的串行会严重的降低系统的吞吐量和资源利用率,仔细发现,引发事务一致性问题的根本原因在于多个事务访问了相同的数据,更合理的做法是,在某个事务访问某个数据时,对其他想要访问该数据的事务进行限制,当该事务提交后,其他事务才能继续访问这个数据

1.2 事务并发执行引发的一致性问题

1.2.1 脏写

一个事务修改了另一个未提交事务修改过的数据,称为脏写
脏写引发的一致性问题,现有两个事务T1和T1,都要对x,y数据进行修改,一致性需求是x和y相等,先有如下操作顺序
在这里插入图片描述

1.2.2 脏读

一个事务读取了另一个未提交事务修改过的数据,意味着发生了脏读
脏读引发的事务一致性问题:一致性需求是x和y的值始终相同
在这里插入图片描述
对于事务T2来说,读取到的是x为1,y为0,得到了一个不一致的状态

1.2.3 不可重复读

一个事务修改了另一个未提交事务修改过的数据,意味着发生了不可重复读现象

不可重复读引发的一致性问题:在这里插入图片描述
事务T1读到的x为0,y为1,是一个不一致状态。
关于不可重复读更严格的解释是,事务T1读取了x的值,之后T2修改了x的值并提交事务T2,随后T1再次读取x的值,发现两次读取到的x值不同

1.2.4 幻读

一事务根据某个搜索条件查询出一些记录,在该事务未提交时,另一个事务写入了一些符合搜索条件的记录,就意味着发生了幻读现象

另一种对于幻读更严格的解释是,T1先读取符合搜索条件的记录,然后T2写入了符合搜索条件的记录,T1再次根据搜索条件读取,发现两次读取到的记录不一样

1.3 SQL标准中的四种隔离级别

设置隔离级别的目的是,舍弃一部分隔离性换取一部分性能,SQL标准中的4个隔离级别:
在这里插入图片描述

1.4 MySQL中支持的4中隔离级别

MySQL中的隔离级别与SQL标准中隔离级别的区别在于,MySQL在REPEATABLE READ隔离级别下,可以很大程度上禁止幻读现象发生。

MySQL中的默认隔离级别是:REPEATABLE READ

设置隔离级别的SQL语句:
set [global | session] transaction isolation level 隔离级别;

二、MVCC原理

2.1 版本链

在InnoDB存储引擎中的表,聚簇索引中的记录都包含两个隐藏列,
trx_id:一个事务都某条聚簇索引记录进行修改时,都会把该事务的事务id赋值给trx_id
roll_pointer:每次对聚簇索引记录进行改动时,都会把旧的版本写入到undo日志中,相当于一个指针,通过它可以找到该记录修改前的信息

现有两个事务id分别为100,200,对同一条记录进行UPDATE操作,操作流程:在这里插入图片描述
形成的版本链:
在这里插入图片描述
利用记录的版本链来控制并发事务访问相同记录时的行为,把这种机制叫做MVCC

2.2 ReadView

用阻AD UNCOMMITTED 隔离级别的事务来说,可以读取未提交事务修改的记录,因此直接读取版本链中的最新版本就可以了;对于SERIALIZABLE隔离级别的事务来说,InnoDB中使用加锁的方式访问记录,对于READ COMMITED和REPEATABLE READ隔离级别的事务来说,都必须保证读到的记录是已经提交的事务修改过的记录,因此核心问题就是:需要判断版本链中的哪个版本对于当前事务是可见的,InnoDB给出的解决方案是,生成ReadView,ReadView包含下列四个重要内容:

  • m_ids:生成ReadView时,当前系统中活跃的事务id列表

  • min_trx_id:m_ids中的最小事务id

  • max_trx_id:在生成ReadView时,系统分配个下一个事务的事务id

  • creator_trx_id:生成该ReadView的事务的事务id

生成了ReadView之后,我们就可以借助它来判断当前版本的记录对当前事务是否可见:

  • 如果当前记录的trx_id与creator_trx_id相同,意味着当前事务在访问自己修改过的记录,可以访问
  • 如果当前记录的trx_id小于min_trx_id,说明生成该版本记录的事务已经提交了,可以访问
  • 如果当前记录的trx_id 大于max_trx_id,说明生成该版本的事务在当前事务生成ReadView之后才开启,所以该版本不可以被当前事务访问
  • 如果被访问版本的trx_id 在 min_trx_id 和 max_trx_id之间,则需进一步判断trx_id是否在m_ids列表中,如果在说明事务为提交,该版本不可见,如果不在,说明可见

在MySQL中,READ COMMITED和REPEATABLE READ 隔离级别之间一个非常答的区别就是他们生成ReadView的时机不同

2.3 READ COMMITED 每次读取数据前都生成一个ReadView

例如,现在系统中有两个事务id为100,200的事务正在执行,此时某个表中number为1的记录对应的版本链为:
在这里插入图片描述
假设现在有一个使用READ COMMITED隔离级别的新事物开始执行:执行语句为在这里插入图片描述
select语句执行过程如下:
(1)执行select语句时生成一个ReadView,m_ids列表为[100,200],min_trx_id为100,max_trx_id为201,creator_trx_id为0

因为这个新开启的事务只进行了select操作,并没有对记录进行修改,所以系统没有为其分配事务id,默认为0

(2)顺序版本链寻找符合要求的版本,返回的是name为"刘备"的版本

之后,将事务id为100的事务提交
事务 200 事务中更新表 hero number 的记录
在这里插入图片描述
然后再到刚才使用 READ COMMITTED隔离级别的事务执行select语句,继续查找number为1 的记录,执行步骤如下:
(1)生成ReadView,m_ids列表[200],min_trx_id为200,max_trx_id为200,creator_trx_id为0
(2)顺序版本链,查找符合要求的版本,最终返回的是"张飞"

2.4 REPEATABLE 在第一次读取数据时生成一个ReadView

假设现在有一个使用 REPEATABLE READ 隔离级别的新事务开始执行:
第一次select操作时:
(1)生成ReadView,执行select语句时生成一个ReadView,m_ids列表为[100,200],min_trx_id为100,max_trx_id为201,creator_trx_id为0
(2)找到符合条件的版本"刘备"

之后将事务id为100的事务提交后,再到事务id为200的事务中更新表中number为1的记录在这里插入图片描述
然后再次执行select:
(1)沿用第一次select时生成的ReadView
(2)最终的返回版本还是"刘备"

总结,在REPEATABLE READ隔离级别下,事务的两次查询结果是一样的,因此可以说在REPEATABLE READ级别下避免了不可重复读的发生,同时也很大程度上避免了幻读的发生

2.5 MVCC小结

所谓的MVCC指的就是在使用READ COMMITED 和 REPEATABLE READ这两种隔离级别的事务在执行select操作时,访问记录版本链的过程,这样可以使不同事务的读-写操作并发执行,从而提升系统性能。READ COMMITED 和 REPEATABLE READ的最大区别在于,生成Read View的时机不同,READ COMMITED 每次执行select前都会生成一个新的ReadView,而REPEATABLE READ只在第一次执行select前生成一个ReadView

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

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

相关文章

使用独立显卡安装黑苹果,但无法扩展显示器的解决方案

使用独立显卡安装黑苹果,但无法扩展显示器的解决方案 网上的教程 本文的外部链接🔗 引用文中的一句话:“这也许是无法驱动独显的黑苹果笔记本想要外接显示器的唯一方案。” ---- 购买拥有displaylink的外置显卡的usb转接器 文章作者给我了…

word@菜单自定义和公式输入

菜单栏快捷键设置 word 设置(选项) Word options (General) - Microsoft Support 点击文件->选项 自定义word菜单 自定义功能区 Customize the ribbon in Word - Microsoft Support Customizing the source list of commandsThe ribbon listAdd or remove commandsReor…

[golang Web开发] 2.golang web开发:操作数据库,增删改查,单元测试

简介 Go 语言中的 database/sql包定义了对数据库的一系列操作,database/sql/driver包定义了应被数据库驱动实现的接口,这些接口会被sql包使用.但是 Go语言没有提供任何官方的数据库驱动,所以需要导入第三方的数据库驱动,不过连接数据库之后对数据库操作的…

超经典JavaIDEA 10个插件 Java开发工程师

工欲善其事,必先利其器。 作为一名合格的程序员,合理配置我们所用的IDEA,是高效开发的必修课。而如今的插件工具也越来越好用,不仅基本具备了智能提示,还可以自动补全代码,甚至能够在查出bug的同时提供修改…

如何彻底删除硬盘数据?电脑高手也恢复不了

实用的小命令,就是彻底删除硬盘上的数据,硬盘恢复软件也恢复不了! 1.以管理员身份运行cmd窗口,打开cmd,如下图所示: 2.在命令提示窗口中,直接输入cipher /w:路径,输入这个命令加上路径即可将文件彻底删除! 可以从整个命令说明上看到是从整个卷上可用的未使用磁盘空间…

Git (2) :Git练习--分支的新建与合并

一.首先有个问题 ? 在进行git练习前,有个问题需要提下。。。。 csdn无法登录了。 查了一下资料,是因为CSDN服务器的各地相应速度不一样,辽宁的响应是超时的,所以通过在hosts文件中指定域名http://csdnimg.cn的服务器…

机器学习之卷积操作

很多好主意一旦踏上语义鸿沟,就再也听不到。 卷积,在图像、视觉领域乃老生常谈的内容,但是对于具体工作细节仍然值得我去学习。 卷积原理 卷积,就是利用一个小的矩阵(或者更高维向量)作用于图像矩阵(或者特征矩阵),然…

Web测试、APP测试常用技巧(错过你一定会后悔)

目录 1. web元素定位七种方式 2. app元素定位3种方式 3. adb常用命令 4. 键盘操作常用函数 5. 鼠标操作常用函数 6. apppium: 7. fixture 1. web元素定位七种方式 优先使用的6种 find_element_by_id (返回一个元素)find_element(s)_by_class_name (根据类名…

2023-02-01 pthread线程局部数据-记录

摘要: pthread线程局部数据-记录 参考: https://www.akkadia.org/drepper/tls.pdf https://en.wikipedia.org/wiki/Thread-local_storage https://download.csdn.net/download/adofsauron/87408865 测试代码: 示例一: #include<stdio.h> #include<stdlib.h> #…

pip install timeout错误解决方案

大家好&#xff0c;我是爱编程的喵喵。双985硕士毕业&#xff0c;现担任全栈工程师一职&#xff0c;热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。喜欢通过博客创作的方式对所学的知识进行总结…

java spring Bean生命周期

首先 要搞清楚大概念 什么是生命周期&#xff1f; 学过vue和react的前端会有概念 简单说 就是一个对象从创建到销毁的整个过程 那么 bean的生命周期 我们先文字描述 然后再看效果 第一 阶段 通过构造器创建bean实例 就是找到bean对象配置的 类中的无惨构造 创建对象 第二阶段…

React学习笔记-(Bilibili李立超)

写法的变更 之前 const divNode <div>你好,React</div> ReactDOM.render(divNode,document.getElementById(root))会警告 现在 <script type"text/babel">const divNode <div>你好,React</div>const root ReactDOM.createRoot(…

【PHP 随记】—— laravel 项目环境搭建

&#x1f449;总目录&#x1f448;\large\colorbox{skyblue}{&#x1f449;总目录&#x1f448;}&#x1f449;总目录&#x1f448;​ 文章目录1、安装 laravel 以及 phpstorm 开发插件2、配置虚拟主机与绑定 hosts 文件① 配置虚拟主机② hosts 绑定③ 验证3、配置数据库① 配…

【MyBatis持久层框架】使用Java注解完成CRUD详细解读

文章目录1. 前言2. 实战案例2.1 准备工作2.2 编写接口方法2.3 映射SQL语句2.4 编写测试方法3. SQL语句构建器4. 总结1. 前言 之前我们通过 XML 配置文件的方式映射 sql 语句&#xff0c;将 sql 语句与 Java 代码分离&#xff0c;大大的提高了开发的效率并且解决了 JDBC 原生方…

MySQL - 为什么索引存储要用B+树,用链表不行吗?

MySQL - 为什么索引存储要用B树&#xff0c;用链表不行吗&#xff1f; 时间&#xff1a;2023年2月1日22:19:09 一、先来比较一下链表和树&#xff1f; 二、为什么数据库索引要用B树&#xff1f; 为什么要用索引&#xff0c;数据直接Load到内存里查不可以吗&#xff1f;&#…

Hive最全总结,学习与面试,收藏这一篇就够了!

Hive基础概念和用途 Hive是Hadoop下的顶级 Apache项目&#xff0c;早期的Hive开发工作始于2007年的 Facebook。 ⬛ Apache Hive是一款建立在Hadoop之上的开源数据仓库系统&#xff0c;可以将存储在Hadoop文件中的结构化、半结构化 数据文件映射为一张数据库表&#xff0c;基…

操作系统(day05)-- 进程调度、调度算法

文章目录进程调度&#xff08;低级调度&#xff09;进程调度的时机进程调度的方式调度算法的评价指标FCFS&#xff0c;SJF&#xff0c;HRRN调度算法先来先服务&#xff08;FCFS&#xff09;短作业优先&#xff08;SJF&#xff09;高响应比优先&#xff08;HRRN&#xff09;进程…

从0开始用hooks搭建一个事件待办的demo(一)

需求一&#xff1a;实现header&#xff0c;点击加号展示input&#xff0c;再次点击隐藏input 分析&#xff1a; 首先&#xff0c;需要两个子组件header和addInput&#xff1b; header组件负责展示图一的内容&#xff0c;给加号添加一个点击事件&#xff0c;来触发展示input的函…

zookeeper源码分享五 --- 数据结构

zookeeper 内存数据结构 zookeeper在内存当中是有一份完整的数据&#xff0c;底层数据结构是基于hashMap去实现的。 在map的key是path&#xff0c;value是具体节点信息(DataNode)。 在map的顶层中有所有节点的path信息&#xff0c;每个节点都要子节点的path(不是具体的节点信息…

图的存储与遍历

目录 一.邻接矩阵 1.1概念介绍 1.2代码示例 1.3代码测试 二.邻接表 2.1概念介绍 2.2代码示例&#xff1a; 2.3代码测试 三.遍历 3.1广度优先遍历&#xff08;BFS&#xff09; 3.1.1邻接表&#xff08;BFS&#xff09; 3.1.2邻接矩阵&#xff08;BFS&#xff09; 3.2深…