MVCC学习记录

embedded/2025/3/10 4:43:52/

   MVCC又叫多版本并发控制,用来解决脏读,不可重复读,以及配合锁解决幻读问题,在保证隔离性基础上,提升了读取效率和并发性。

  (一)版本链

  MVCC是基于一个undolog版本链和readview来实现的,我们知道undolog是可以保证我们的原子性的,作为一个回滚日志,不仅记录了我们dml操作之前的数据,同样记录了我们操作的一个反向操作,此外每条undolog还记录一个叫做roll_pointer这个引用信息,通过这个引用信息,我们可以简单把他理解为链表中的next(指向下一个节点),我们就可以把某一条数据对应的undolog日志组织成一个undo链,这样这个undo链就记录这这个数据的变化

  如下所示

  我们看到每个数据行存储了对应的主键id,以及是那个事务修改的对应值的事务id,一个roll_pointer指向下一个数据行,之后就全是数据了

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

注:这里我们能看到是存储了事务id的,那么也就是说,版本链是在所有事务中共享,也就是说所有事务访问的都是同一条版本链

 (二)ReadView

   每条数据的版本链都构造好之后,我们查询时要访问版本链的哪一行数据,我们就需要使用ReadView结构来实现,其实ReadView就是一个内存结构,本质是一个视图,在事务使用select查询时,我们就会自动生成一个ReadView,我们具体来看一下都有什么

  我们根据上面的各种id就能判断,哪些数据值是我们当前这个事务可以获取的,哪些数据值是对我们当前事务不可见的,就比如说我们如果undo链中的一个事务id<活跃集合的最小id,那我们就是可以获取到

 我们用一个具体例子来说,就比如我们当前事务id为201,执行select会构造一个readview

此时假设我们活跃事务除了我们还有三个事务(90,100,200)

那我们上面四个参数存的值分别为

此时我们要从版本链中获取数据

  我们不可以获取活跃事务id的数据,所以我们目前只能获取比最小活跃id小的(已提交事务)的一个数据

  我们获取的规则总结如下:

  从undo链头来遍历所有版本

第一步:判断该版本是否为当前事务创建(当前事务创建的数据是可以获取到的,是为了保证我们事务内数据的一致性),也就是m_creator_trx_id等于该版本事务id,意味着读自己修改数据,可以直接访问,如果不是则看第二步

第二步:若该版本事务id<m_up_limit_id(最小事务id),意味着在该版本在readView生成之前已经提交,可以直接访问,如果不是则看第三步

第三步:或该版本事务id>=m_low_limit_id(最大事务id),意味着该版本在readview之后才创建,那么我们是读不到的,直接遍历下一个版本,无需其他判断

第四步:如果该版本的事务id在m_up_limit_id和m_low_limit_id之间,同时不在活跃事务列表中,那么就说明我们创建readview时,这个事务就已经提交了,可以访问,无需其他遍历

  这样我们从版本链头遍历一直到链尾,找到每一个符合要求的版本就可以,所以查找到的事务都是已经提交的事务,这样就避免了  “ 脏读 ”

MVCC解决问题

  脏读:我们mvcc通过各个id来保障我们读到的undo链中的数据行都是已经提交的事务,所以不会读到未提交的事务,来确保我们不出现脏读问题

 不可重复读:我们刚刚说readview在可重复读下,只会在第一次select时创建,以后我们每一次select都会读取这一个readview中的数据,这样就不存在我们在同一个事务中两次读取同一条数据会出现数据不一样的问题了

注:我们说只有在可重复读以及以上是只创建一个readView的,如果是读已提交,那么每一次select都会创建一个readView,此时会出现不可重复读的问题

 幻读:我们幻读是无法单独通过mvcc来解决的,我们需要通过锁配合mvcc来解决,mvcc来确保稳定的数据版本,而锁(next-key)来保证我们的我们的间隙不被插入,防止我们多次查询出的数据集不同

 注:我们说可重复读下,我们只创建一个readView,之后每一次查询都会使用我们第一次创建的readview,那么我们如果当前事务进行了修改,我们能够正确的读到信息吗?

答案是可以的,这是因为我们要确保事务内数据的一致性


http://www.ppmy.cn/embedded/171398.html

相关文章

从零开始实现大语言模型(十四):高阶训练技巧

1. 前言 预训练大语言模型的流程与训练普通神经深度网络模型本质上并没有任何不同。可以使用深度学习实践中已经被证明非常有效的高阶训练技巧&#xff0c;优化大语言模型预训练流程&#xff0c;使大语言模型预训练效率更高&#xff0c;训练过程更稳定。 本文介绍深度学习领域…

【leetcode hot 100 234】回文链表

错误解法一&#xff1a;正序查找的过程中&#xff0c;将前面的元素倒叙插入inverse链中&#xff0c;找到偶数中点时&#xff0c;对称查找。 /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode() {}* Li…

Kotlin和Java区别

哈哈哈&#xff0c;前段时间&#xff0c;面试的时候&#xff0c;突然问到我Kotlin和Java的区别&#xff0c;一下子把我问懵逼了&#xff0c;确实没遇到问这个的&#xff0c;想了下&#xff0c;说了下Kotlin的编译时空检查机制&#xff0c;代码更简洁&#xff0c;很多封装好的AP…

使用AI整理知识点--WPF动画核心知识

一、WPF动画基础 1、动画本质 通过随时间改变依赖属性值实现视觉效果&#xff08;如位置、透明度、颜色等&#xff09;。 依赖属性必须支持 DependencyProperty&#xff0c;且需是可动画的&#xff08;如 Double, Color, Point 等&#xff09;。 2、动画三要素 起始值 (Fr…

Windows 远程桌面多端口访问,局域网虚拟IP映射多个Windows 主机解决方案

情景 项目现场4G路由局域网中两台主机通过VPN连接到公司内网&#xff0c;实现远程管理&#xff0c;要求映射两个Windows 桌面进行管理。 目录 情景 网络 思路 已知 问题解决 1.客户端通过VPN进入内网路由器配置NAT 2.使用远程主机远程桌面功能&#xff1a;IP端口号访问 …

【音视频】RTP封包H265信息

RTP 含义 RTP 是一种专门为 实时数据传输 设计的网络协议。这里的 "实时数据" 主要指的是 音频 和 视频 这类对传输延迟非常敏感的数据。想象一下&#xff0c;你在进行视频通话或者观看在线直播&#xff0c;你希望画面和声音能够流畅地、几乎同步地到达&#xff0c;而…

无人机扩频技术对比!

一、技术原理与核心差异 FHSS&#xff08;跳频扩频&#xff09; 核心原理&#xff1a;通过伪随机序列控制载波频率在多个频点上快速跳变&#xff0c;收发双方需同步跳频序列。信号在某一时刻仅占用窄带频谱&#xff0c;但整体覆盖宽频带。 技术特点&#xff1a; 抗干扰…

3.4 数据结构之递归

递归 定义&#xff1a; 计算机科学中&#xff0c;递归是一种解决计算问题的方法&#xff0c;其中解决方案取决于同一类问题的更小自己 说明&#xff1a; 1.自己调用自己&#xff0c;如果说每个函数对应这一种解决方案&#xff0c;自己调用自己意味着解决方案是一样的&#x…