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

MySQL:MVCC原理详解

        MySQL是允许多用户同时操作数据库的,那么就会出现多个事务的并发场景。那么再并发场景会出现很多问题:脏读、不可重复读、幻读的问题。

而解决这些问题所用到的方法就是:MVCC 多版本并发控制。而这个MVCC的实现是基于read_view、undoLog

如果不了解这几种问题的概念可以看这两篇博客:

MySQL:事务隔离级别详解,MySQL:三大日志(binlog、redo log、undo log)

1、 reda_view

        read view是一个数据库的内部快照,它记录了数据库在某个时刻的数据信息。read view用于实现事务的隔离性,即在并发事务中,一个事务能看到哪些数据,以及哪些数据对其他事务不可见。read view的生成时机和事务的隔离级别有关,例如,在可重复读隔离级别下,read view会在事务开始时生成,而在读已提交隔离级别下,read view会在每条查询语句执行时生成。

除了记录着数据之外,它还记录着几个变量来辅助我们来判定可见性。

  • min_trx_id:在生成Read View时,当前系统中活跃的读写事务中最小的事务ID,即m_ids中的最小值;
  • max_trx_id:最后开始的事务,该SQL启动时,当前事务链表中最大的事务id编号,也就是最近创建的除自身以外最大事务编号。
  • m_ids:在生成Read View时,当前系统中活跃的读写事务的事务ID列表;
  • creator_trx_id:在生成Read View时,当前事务的事务ID。

 reda_view的判断规则:

  • 如果事务id小于min_trx_id,表示该事务在read view生成之前已经提交,所以对当前事务可见。
  • 如果事务id大于max_trx_id,表示该事务在read view生成之后才开始,所以对当前事务不可见。
  • 如果事务id在min_trx_id和max_trx_id之间,那么需要查看该事务id是否在m_ids中。如果在,表示该事务在read view生成时仍在活跃,所以对当前事务不可见;如果不在,表示该事务在read view生成之前已经提交,所以对当前事务可见。

2、undo log

        MVCC中判断可见性判断的就是下面这个undo log的版本链,假设要查询id为1的记录的姓名,此次事务id(trx_id)为63,那么版本链第一个看到事务id为66,假设此时创建的reda_view中的max_trx_id为65,那就说明名字为小吴的是再此次查询创建reda_view后才进行的修改,所以对此次的查询事务不可见。所以查询出来的应该是小王。

3、MVCC实现 可重复读 和 读已提交

上图再没有使用MVCC版本控制的时候,会出现上面这种问题,再一个事务中读取两次得到的结果不想同,这个就是不可重复读的问题,那么MVCC是只会再第一次查询语句时生成read_View快照,

  1. 事务A第一次查询查出来很正常是“小王”,
  2. 再第二次查询前事务B提交,将小王改为小吴。
  3. 然后事务A进行第二次查询,根据第一次查询时生成的read_View中,根本没有这条记录,则此条记录对A来说是不可见的,所以查询出来的还是小王。

如果是读已提交的隔离级别,则是每执行一次查询语句都会生成reda _View,这样也就能再第二次读的时候生成新的read_View ,然后看到版本链中改成小吴的这条undo log日志了。然后进行可见性判断,此时事务Bid>事务Aid,但又不在活跃事务列表中。说明生成此次快照时,事务B已经提交了,所以条记录对于事务A来说是可见的。

4、幻读的解决

  • 针对快照读(普通 select 语句),可重复读隔离级别下,事务执行过程中看到的数据,一直跟这个事务启动时看到的数据是一致的,即使中途有其他事务插入了一条数据,是查询不出来这条数据的,所以就很好了避免幻读问题。
  • 针对当前读(select ... for update 等语句),是通过 next-key lock(记录锁+间隙锁)方式解决了幻读,因为当执行 select ... for update 语句的时候,会加上 next-key lock,如果有其他事务在 next-key lock 锁范围内插入了一条记录,那么这个插入语句就会被阻塞,无法成功插入,所以就很好了避免幻读问题。

相关文章:

  • java:实现查询MySQL数据库中的数据,并导出excel、pdf类型文档(超详细)
  • Unity 命令模式(实例详解)
  • HCIA-HarmonyOS设备开发认证-3.内核基础
  • GO——SELECT
  • 高光谱图像加载、归一化和增强(jupyter book)
  • 【JavaEE】UDP协议与TCP协议
  • 用Flask打造一个大模型智能问答WEB网站
  • 温酒读Qt:QObject中篇2 ——欲遮还羞的 QObjectPrivate
  • OSPF协议解析及相关技术探索(C/C++代码实现)
  • C++核心编程:文件操作 笔记
  • Java+Spring Cloud +Vue+UniApp微服务智慧工地云平台源码
  • 【kafka-01数据保留时间设置】
  • 有序数组查找两数之和(c++题解)
  • Unity中创建Ultraleap 3Di交互项目
  • 螺旋遍历二维数组【leetcode】
  • 【每日笔记】【Go学习笔记】2019-01-10 codis proxy处理流程
  • 【刷算法】求1+2+3+...+n
  • 2019.2.20 c++ 知识梳理
  • Android框架之Volley
  • co.js - 让异步代码同步化
  • JavaScript创建对象的四种方式
  • PyCharm搭建GO开发环境(GO语言学习第1课)
  • ------- 计算机网络基础
  • 技术胖1-4季视频复习— (看视频笔记)
  • 解析带emoji和链接的聊天系统消息
  • 前端相关框架总和
  • 使用前端开发工具包WijmoJS - 创建自定义DropDownTree控件(包含源代码)
  • 原生js练习题---第五课
  • #LLM入门|Prompt#1.7_文本拓展_Expanding
  • (9)目标检测_SSD的原理
  • (pojstep1.3.1)1017(构造法模拟)
  • (TOJ2804)Even? Odd?
  • (附源码)计算机毕业设计大学生兼职系统
  • (南京观海微电子)——I3C协议介绍
  • .NET Core WebAPI中使用swagger版本控制,添加注释
  • .NET 将混合了多个不同平台(Windows Mac Linux)的文件 目录的路径格式化成同一个平台下的路径
  • .net 托管代码与非托管代码
  • .NET版Word处理控件Aspose.words功能演示:在ASP.NET MVC中创建MS Word编辑器
  • .NET命名规范和开发约定
  • .Net转Java自学之路—基础巩固篇十三(集合)
  • @Resource和@Autowired的区别
  • [AIGC] Java 和 Kotlin 的区别
  • [Android Pro] android 混淆文件project.properties和proguard-project.txt
  • [AutoSar]BSW_Memory_Stack_004 创建一个简单NV block并调试
  • [C++]类和对象(中)
  • [ccc3.0][数字钥匙] UWB配置和使用(二)
  • [LeetCode]—Implement strStr() 寻找子串匹配第一个位置 (KMP)
  • [Oracle]4--查询操作
  • [React源码解析] Fiber (二)
  • [ROS2] --- ROS diff ROS2
  • [StartingPoint][Tier1]Pennyworth
  • [webpack] devtool里的7种SourceMap[转]
  • [程序员学英语]英语国际音标
  • [代码审计] beecms 4.0 漏洞总结
  • [工具]ps