MySQL MVCC详解

目录

 前言

MVCC实现原理

UndoLog版本链

 ReadView

MVCC是否可以解决不可重复读与幻读

隔离级别

READ UNCOMMITTED - 读未提交与脏读

READ COMMITTED - 读已提交与不可重复读

REPEATABLE READ - 可重复读与幻读

SERIALIZABLE - 串行化

小结


 前言

    为了提高数据库并发能力,首先应该想到的就是多线程,但是多线程带来的线程安全问题又不得不考虑。通常采用加锁解决,但这个锁的粒度和锁策略是至关重要的。MVCC全称MultiVersioned ConcurrencyControl(多版本并发控制),MVCC使用了锁、UndoLog以及ReadView配合来完成这件事情。

MVCC实现原理

UndoLog版本链

    MVCC的实现是基于 Undo Log 版本链和 ReadView 来完成的,Undo Log做为回滚的基础,在执行Update或Delete操作时,会将每次操作的上一个版本记录在Undo Log中,每条Undo Log中都记录⼀个叫做 roll_pointer 的引用信息,通过 roll_pointer 就可以将某条数据对应的Undo Log组织成⼀个Undo链,在数据行的头部通过数据行中的 roll_pointer 与Undo Log中的第⼀条日志进行关联,这样就构成一条完整的数据版本链。

    每一条被修改的记录都会有一条版本链,体现了这条记录的所有变更,当有事务对这条数据进行修改时,将修改后的数据链接到版本链接的头部。

 ReadView

    每条数据的版本链都构造好之后,在查询时具体选择哪个版本呢?这⾥就需要使用 ReadView 结构来实现了,所谓 ReadView 是⼀个内存结构,顾名思义是⼀个视图,在事务使用 select 查询数据时就会构造⼀个ReadView,里面记录了该版本链的一些统计值,这样在后续查询处理时就不用遍历所有版本链了,这些统计值具体包括:

  • m_ids :当前所有活跃事务的集合(活跃事务:未提交的事务)
  • m_low_limit_id :活跃事务集合中最小事务Id
  • m_up_limit_id :下⼀个将被分配的事务Id,也就是 版本链头的事务Id + 1 
  • m_creator_trx_id :创建当前 ReadView 的事务Id

    构造好 ReadView 之后需要根据一定的查询规则找到唯一的可用版本,会在UndoLog版本连中找到select查询具体记录版本的链头,从链头开始遍历所有版本,根据四步查找规则,判断每个版本是否符合要求,如果某个版本符合要求则返回该版本数据。

  • 第一步:判断该版本是否为当前事务创建,若 m_creator_trx_id 等于该版本事务id,意味着读取自己修改的数据,可以直接访问,如果不等则到第二步
  • 第⼆步:若该版本事务Id < m_up_limit_id (最⼩事务Id),意味着该版本在ReadView⽣成之前已经提交,可以直接访问,如果不是则到第三步
  • 第三步:若该版本事务Id >=  m_low_limit_id (最大事务Id),意味着该版本在ReadView生成之后才创建,所以肯定不能被当前事务访问,因为该条记录无法判断是否提交,所以无需第四步判断,直接遍历下一个版本,如果不是则到第四步
  • 第四步:若该版本事务Id在 m_up_limit_id (最小事务Id)和 m_low_limit_id (最大事务Id)之间,同时该版本不在活跃事务列表中,意味着创建ReadView时该版本已经提交,可以直接访问,如果不是则遍历并判断下一个版本

    这样从版本链头遍历判断到版本链尾,找到⾸个符合要求的版本即可,就可以实现查询到的结果都是已经提交事务的数据,那么就可以解决脏读问题。

MVCC是否可以解决不可重复读与幻读

  • ⾸先幻读无法通过MVCC单独解决,InnoDB在可重复读隔离级别下使用临建锁,锁住某条记录以及该记录之前的间隙,可以解决大部分幻读问题,但无法从根本上解决幻读问题
  • 对于不可重复读问题,在事务中的第⼀个查询时创建⼀个ReadView,后续查询都是⽤这个ReadView进行判断,所以每次的查询结果都是一样的,从而解决不可重复读问题,在REPEATABLE READ 可重复读,隔离级别下就采用的这种方式
  • 如果事务每次查询都创建⼀个新的ReadView,这样就会出现不可重复读问题,因为不同的ReadView中参数可能不一致,那么在UndoLog中找到的数据就可能不一致,在 READ COMMITTED 读已提交的隔离级别下就是这种实现方式

    这些机制加上锁就可以实现MySQL的四种隔离性 

隔离级别

READ UNCOMMITTED - 读未提交与脏读

实现方式

  • 读取时:不加任何锁,直接读取版本链中的最新版本,也就是当前读,可能会出现脏读,不可重复读、幻读问题
  • 更新时:加共享行锁(S锁),事务结束时释放,在数据修改完成之前,其他事务不能修改当前数据,但可以被其他事务读取

存在问题 

    事务的 READ UNCOMMITTED 隔离级别不使用独占锁,所以并发性能很高,但是会出现大量的数据安全问题。

    比如在事务A中执行了一条 INSERT 语句,在没有执行 COMMIT 的情况下,会在事务B中被读取到,此时如果事务A执行回滚操作,那么事务B中读取到事务A写入的数据将没有意义,这个现象叫做 "脏读"。

注意:

    由于 READ UNCOMMITTED 读未提交会出现"脏读"现象,在正常的业务中出现这种问题会产生非常危重后果,所以正常情况下应该避免使用 READ UNCOMMITTED 读未提交这种的隔离级别。

READ COMMITTED - 读已提交与不可重复读

实现方式

  • 读取时:不加锁,但使⽤快照读,即按照 MVCC 机制读取符合 ReadView 要求的版本数据,每次查询都会构造一个新的 ReadView ,可以解决脏读,但无法解决不可重复读和幻读问题
  • 更新时:加独占行锁(X),事务结束时释放,数据在修改完毕之前,其他事务不能修改也不能读取这行数据

存在问题

    为了解决脏读问题,可以把事务的隔离级别设置为 READ COMMITTED ,这时事务只能读到了其他事务提交之后的数据,但会出现不可重复读的问题,核心原因就是每次快照读都会构造新的ReadView。

    比如事务A先对某条数据进行了查询,之后事务B对这条数据进行了修改,并且提交( COMMIT )事务,事务A再对这条数据进行查询时,得到了事务B修改之后的结果,这导致了事务A在同一个事务中以相同的条件查询得到了不同的值,这个现象要"不可重复读"。

REPEATABLE READ - 可重复读与幻读

实现方式

  • 读取时:不加锁,也使⽤快照读,按照MVCC机制读取符合ReadView要求的版本数据,但无论事务中有几次查询,只会在⾸次查询时生成一个ReadView,可以解决脏读、不可重复读,配合Next-Key行锁可以解决一部分幻读问题
  • 更新时:加Next-Key行锁,事务结束时释放,在一个范围内的数据修改完成之前,其他事务不能对这个范围内的数据进行修改、插入和删除操作,同时也不能被查询

存在问题

    事务的 REPEATABLE READ 隔离级别是会出现幻读问题的,在 InnoDB 中使用了Next-Key行锁来解决大部分场景下的幻读问题,那么在不加 Next-Key 行锁的情况下会出现什么问题吗?

    使用 Next-Key 锁,锁住的是当前索引记录以及索引记录前面的间隙,那么在不加 NextKey 锁的情况下,也就是只对当前修改行加了独占行锁(X),这时记录前的间隙没有被锁定,其他的事务就可以向这个间隙中插入记录,就会导致一个问题如下:

    比如事务A查询了一个区间的记录得到结果集A,事务B向这个区间的间隙中写入了⼀条记录,事务A再查询这个区间的结果集时会查到事务B新写入的记录得到结果集B,两次查询的结果集不一致,这个现象就是"幻读“ 。

SERIALIZABLE - 串行化

实现方式

  • 读取时:加共享表锁,读取版本链中的最新版本,事务结束时释放
  • 更新时:加独占表锁,事务结束时释放,完全串行操作,可以解决所有事务问题

存在问题 

    所有的更新都是串行操作,效率极低

小结

    当理解了不同隔离级别下实现原理与所存在的问题时,可以修改数据库隔离级别进行问题重现,理论与实操结合,相信你会有很大收获。

这里提供一些可能会用到的命令

# 开启事务
START TRANSACTION;
# 提交事务
commit;
# 回滚事务
rollback;
# 查看全局作用域隔离级别
SELECT @@GLOBAL.transaction_isolation;
# 查看会话作用域隔离级别
SELECT @@SESSION.transaction_isolation;
# 通过GLOBAL|SESSION分别指定不同作用域下隔离级别
SET [GLOBAL|SESSION] TRANSACTION ISOLATION LEVEL level|access_mode;
# 隔离级别level: REPEATABLE READ # 可重复读READ COMMITTED # 读已提交READ UNCOMMITTED # 读未提交SERIALIZABLE # 串⾏化
# 访问模式access_mode: READ WRITE # 表⽰事务可以对数据进⾏读写READ ONLY # 表⽰事务是只读,不能对数据进⾏读写

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

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

相关文章

GNSS接收机的工作原理

GNSS接收机的工作原理如下&#xff1a; 信号接收&#xff1a;GNSS接收机通过天线接收来自卫星导航系统的信号&#xff0c;这些信号包含卫星的位置、时间和健康状态等信息。 信号处理&#xff1a;接收的信号首先经过前置放大器放大&#xff0c;然后经过滤波器滤除噪声。接收机会…

邂逅Three.js探秘图形世界之美

可能了解过three.js等大型的3D 图形库同学都知道啊&#xff0c;学习3D技术都需要有图形学、线性代数、webgl等基础知识&#xff0c;以前读书学的线性代数足够扎实的话听这节课也会更容易理解&#xff0c;这是shader课程&#xff0c;希望能帮助你理解着色器&#xff0c;也面向第…

图象去噪1-使用中值滤波与均值滤波

1、中值滤波 使用中值滤波去除图像的异常像素点&#xff0c;使用cv2.cv2.medianBlur(img, 3)表示再图像在中值滤波窗口3*3的范围内&#xff0c;从下到大排序&#xff0c;将当前值替换为排序中值&#xff08;如下图所示&#xff09;将56替换为&#xff08;56&#xff0c;66,90,…

JeecgFlow并行网关概念及案例演示

概念讲解 并行网关能够在一个流程中用于进行并发建模处理&#xff0c;将单条线路拆分成多条路径并行执行&#xff0c;或者将多条路径合并处理。 在一个流程模型中引入并发最直接的网关就是并行网关&#xff0c;它基于进入和外出顺序流&#xff0c;有分支和合并两种行为&#xf…

想拥有一个独一无二的AI人物?Lora炼丹训练模型教程来啦

之前答应过大家放出来的Lora本地训练教程&#xff0c;终于写好啦。 会训练lora&#xff0c;代表着你可以生成属于你的独一无二的角色。 你可以让这个角色在各种不同背景的地方出现&#xff0c;可以让它摆出各种姿势&#xff0c;满足你的无限幻想。 还有的商家&#xff0c;用…

10分钟安装好torch的GPU版本(Windows)

pytorch-gpu 1. 确定cuda版本2. 确定Python版本3 开始下载-cu118-cp383.1 下载cuda3.2 下载torchvision 4.下载好了5.开始安装6. 开始验证 1. 确定cuda版本 nvcc -V 版本为11.8 , 一会下载的版本为cu118 2. 确定Python版本 确定python版本为为3.8&#xff0c;一会下载为cp38 3 …

Java包介绍

今天看jdk文档&#xff0c;顺便写一下java几个包的作用。 java.applet 主要用于创建java applet小应用程序&#xff0c;可以嵌入到网页中能够呈现出特殊的效果&#xff0c;现在基本已经被废弃&#xff0c;很少使用。 java.awt AWT 是Abstract Window ToolKit (抽象窗口工具包…

猫头虎分享已解决Bug: Illegal State Exception: java.lang.IllegalStateException

猫头虎分享已解决Bug: Illegal State Exception: java.lang.IllegalStateException &#x1f42f; 摘要 &#x1f4c4; 大家好&#xff0c;我是猫头虎&#xff0c;一名专注于后端技术的博主。在日常开发中&#xff0c;我们经常会遇到各种各样的Bug&#xff0c;其中Illegal St…

Python基础教程(二十七):urllib模块

&#x1f49d;&#x1f49d;&#x1f49d;首先&#xff0c;欢迎各位来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里不仅可以有所收获&#xff0c;同时也能感受到一份轻松欢乐的氛围&#xff0c;祝你生活愉快&#xff01; &#x1f49d;&#x1f49…

ssl证书90天过期?保姆级教程——使用acme.sh实现证书的自动续期

腾讯云相关文档相关参考-有的点不准确 前言 最近https到期了&#xff0c;想着手动更新一下https证书&#xff0c;结果发现证书现在的有效期只有90天&#xff0c;于是想找到一个自动更新证书的工具&#xff0c;发现了acme.sh&#xff0c;但是网上的文章质量参差不齐&#xff0…

数据结构——二分算法

二分查找 1. 在排序数组中查找元素的第一个和最后一个位置 代码实现&#xff1a; /*** Note: The returned array must be malloced, assume caller calls free().*/int binarySearch(int *nums, int numsSize, int target) {int l 0, r numsSize - 1; while (l <…

【面试题】前端 移动端自适应?_前端移动端适配面试题

设备像素比 设备像素比 (DevicePixelRatio) 指的是设备物理像素和逻辑像素的比例 。比如 iPhone6 的 DPR 是2。 设备像素比 物理像素 / 逻辑像素。可通过 window.devicePixelRatio 获取&#xff0c;CSS 媒体查询代码如下 media (-webkit-min-device-pixel-ratio: 3), (min-…

6.折半查找

折半查找 基本思路在有序表中,取中间元素作为比较对象,若给定值与中间元素的要查找的数相等,则查找成功;若给定值小于中间元素的要查找的数,则在中间元素的左半区继续查找;若给定值大于中间元素的要查找的数,则在中间元素的右半区继续查找。不断重复上述查找过 程,直到查找成功…

揭秘循环购:消费即收益,如何助力商家月销百万?

大家好&#xff0c;我是吴军&#xff0c;今天要和大家分享一种颠覆性的商业模式——循环购。你是否听说过“消费1000送2000”这样的促销活动&#xff1f;是不是觉得太不可思议&#xff0c;商家岂不是在“送钱”&#xff1f;别急&#xff0c;让我为你揭开这背后的秘密。 循环购&…

C和C++实现stack的对比

本篇文章&#xff0c;我们将对比C语言和C实现栈的不同来体会C的魅力&#xff01; 1.栈的介绍 栈&#xff08;Stack&#xff09;是一种常见的数据结构&#xff0c;它是一种特殊的线性表&#xff0c;只允许在一端进行数据的插入和删除操作。这一端通常被称为栈顶&#xff08;Top…

路由器ARP和ARP-proxy(华为)

#交换设备 路由器ARP和ARP-proxy(华为) 当一个广播域中的主机想要访问另外一个广播域的主机时&#xff0c;会广播ARP报文&#xff0c;询问目标IP地址所对应的MAC地址&#xff0c;默认情况下&#xff0c;arp记录是设备自动生成的&#xff0c;但是这样会容易受到ARP欺骗攻击&am…

python实训day4

1、查看数据库的版本 2、查看当前用户 3、查看当前数据库 4、计算表达式的结果; 任何一个数据库,无论大小,都首先是一个超级计算器 5、查看当前MySQL环境中所有的数据库; 系统数据库(只能看)和自定义数据库(任何操作) 6、先建数据库 gaoming 7、如果表已经存在,则创建不能成功 …

【ai】tx2 nx: jetson Triton Inference Server 运行YOLOv4

【ai】tx2 nx: jetson Triton Inference Server 部署YOLOv4 部署了服务端。需要对其测试【ai】tx2-nx 查看 jetpack 版本信息及对应的tritonserver【ai】tx2-nx:配置tritonserver2.17.0-jetpack4.6 环境并运行例子C++ Triton YoloV4 client 是基于 r21.05的 服务端的tensort 的…

springboot3 连接 oceanbase + logproxy数据同步到redis

我这用的是 社区版的 单机&#xff0c; rocky liunx 安装oceanbase 注意事项&#xff1a; logproxy 是 CDC 模式 &#xff0c; springboot 可以直接订阅 canal 是 binlog模式&#xff0c; canal 订阅 logproxy&#xff0c; springboot 订阅 canal logproxy 也可以转 bi…

嵌入式实验---实验七 SPI通信实验

一、实验目的 1、掌握STM32F103SPI通信程序设计流程&#xff1b; 2、熟悉STM32固件库的基本使用。 二、实验原理 1、使用STM32F103R6通过74HC595控制一位LID数码管&#xff0c;实现以下两个要求&#xff1a; &#xff08;1&#xff09;数码管从0到9循环显示&#xff1b; …