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

MVCC -MySQL多版本并发控制

MVCC是多版本并发控制,指的是一条数据记录会有多个版本,每次修改的时候会存储之前的版本,因此MVCC的控制是以一条数据为单位的而不是表。

MVCC能够实现启动的事务无锁地访问不同版本的数据,因此读(普通读)写操作不会受到阻塞。

MVCC有两个重要的概念:即版本链和readView

版本链:

版本链实现了多个版本的存储,其实现原理为当事务改变了数据表的某一条数据时,会附带两个隐藏字段的数据,一个是trx_id,即事务ID,一个是roll_pointer,是指向undolog的指针。

当事务为插入的时候,就会插入生成的trx_id以及roll_pointer,trx_id标识了事务唯一,而roll_pointer则指向mysql自带的一个undolog表,这张表里记录了这次事务的id和修改数据的主键和长度等信息。 然而,由于插入操作本身不会修改现有的行,而是创建新的行,因此这个新行没有前一个版本。数据库在提交该插入事务后,roll_pointer 通常会为空,因为没有旧版本需要回滚, 当这条插入事务提交后,其undolog就会被回收,因为插入数据前是没有回滚的意义的。所以对于插入操作,undolog只在事务未提交时有效,一旦事务提交就会回收。

当执行 UPDATEDELETE 操作时,trx_idroll_pointer 被更新。roll_pointer 指向的 undo log 包含了修改前的旧版本数据。这个 undo log 不仅记录了原始数据,还记录了 roll_pointer 的值,指向再之前的旧版本的 undo log 条目。通过这种方式,多个版本的记录被串联起来,形成所谓的“版本链”。

readView:

readView的作用是说明哪个版本对于新执行的事务而言是可见的,readView只会在有包含查询操作的事务执行的同时存在未提交的增删改事务才会创建,其本质是一个视图。

readView相关的有四个概念,即creator_id(当前事务id),m_ids(生成readView时还活跃的事务id,即还未提交的事务id),min_trx_id(活跃id的最小id),max_trx_id(生成readView时InnoDB将分配给下一个事务的ID的值)。

对于可见版本的判断是沿着版本链逐渐寻找老的版本,如果遇到合适的版本就返回。

判断条件如下:

  • 当trx_id==creator_id时,说明当前事务就是修改数据的事务,(例如在同一个事务中先进行修改再进行查询),所以可见。
  • 当trx_id<min_trx_id的时候,说明当前事务查询的版本是已经提交了的版本,所以可见。
  • 当min_trx_id<trx_id<max_trx_id的时候,如果此时trx_id在m_ids中,说明当前事务还没有提交,因此不可见,如果trx_id不在m_ids中,说明已提交,因此可见。
  • 当trx_id>=trx_max_id,说明修改这条数据的事务在当前事务生成readView的时候还未启动,所以不可见。

当隔离级别是读已提交时:

每一个含有查询的事务都会生成一个readView,而单纯的查询事务的creator_trx_id=0,然后根据判断条件选择最大的trx_id那个可见版本进行查询。

当隔离级别是可重复度时:

在第一次查询生成readView之后,后续的查询都共用这一个readView。

注意:MVCC并不能解决幻读的问题,因为MVCC是针对于数据行(即单条数据)进行的控制,当发生了插入和删除操作的时候,读取的数据集结构就发生了改变,即使对于删除操作而言在可重复度情况下readView是一个readView,但是读取的结果中行数仍然会少那一行,因此仍然会出现幻读。

以MVCC进行的读操作为快照读(即根据readView快照向表中数据进行读取),注意快照读不是从视图读而是按照视图提供的字段向数据表中读取相应的版本数据。

要解决幻读,需要实现当前读,即读取数据的最新数据版本,并且加锁以确保数据一致性。即使其他事物在当前读之后修改了数据,也会立即反映在当前读的结果中。

当前读会在要读取的数据中加锁,即间隙锁,锁定范围内的所有记录和间隙,防止其他事务在该范围内插入新数据。

显示使用间隙锁,可以在查询语句中使用如下结构:

SELECT ... FOR UPDATE:用于在当前事务中锁定所查询的行,并且锁定这些行之间的间隙,防止其他事务插入或删除这些记录。

SELECT ... LOCK IN SHARE MODE:类似于 FOR UPDATE,但允许其他事务读取这些行,而不允许修改或插入新的行。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • LCP142 环形链表[leetcode-7]
  • 中国植物性状数据库
  • 大语言模型 LLM book 笔记(三)第五章 模型架构
  • 16岁可以办手机卡!
  • 信息竞赛2024年第三次csp-j模拟测试赛后总结
  • Qt实现tcp协议
  • SQLite增删改查
  • [数据集][目标检测]绳子检测数据集VOC+YOLO格式322张1类别
  • CSS的:placeholder-shown伪类:精确控制输入框占位符样式
  • 服务器托管:单线机房与双线机房之间的区别
  • 注册Github账号详细过程
  • Vue2父子传值
  • 从0开始搭建一个SpringBoot项目(从环境配置到运行项目)
  • 网络协议(概念版)
  • 【java计算机毕设】学生选课系统小程序MySQL ssm vue uniapp maven项目设计源代码带文档PPT 寒暑假小组课后作业
  • (三)从jvm层面了解线程的启动和停止
  • express + mock 让前后台并行开发
  • HTTP那些事
  • JavaScript DOM 10 - 滚动
  • Linux下的乱码问题
  • Lucene解析 - 基本概念
  • Mysql优化
  • php ci框架整合银盛支付
  • Python学习之路16-使用API
  • SegmentFault 社区上线小程序开发频道,助力小程序开发者生态
  • Spark RDD学习: aggregate函数
  • SQLServer之创建显式事务
  • vue-router 实现分析
  • vue中实现单选
  • Webpack入门之遇到的那些坑,系列示例Demo
  • 记录:CentOS7.2配置LNMP环境记录
  • 如何正确配置 Ubuntu 14.04 服务器?
  • 使用Swoole加速Laravel(正式环境中)
  • 一起来学SpringBoot | 第三篇:SpringBoot日志配置
  • 应用生命周期终极 DevOps 工具包
  • 你对linux中grep命令知道多少?
  • 关于Android全面屏虚拟导航栏的适配总结
  • 树莓派用上kodexplorer也能玩成私有网盘
  • ​zookeeper集群配置与启动
  • # Swust 12th acm 邀请赛# [ E ] 01 String [题解]
  • #Datawhale AI夏令营第4期#AIGC方向 文生图 Task2
  • #微信小程序:微信小程序常见的配置传旨
  • ( )的作用是将计算机中的信息传送给用户,计算机应用基础 吉大15春学期《计算机应用基础》在线作业二及答案...
  • (php伪随机数生成)[GWCTF 2019]枯燥的抽奖
  • (pytorch进阶之路)CLIP模型 实现图像多模态检索任务
  • (react踩过的坑)antd 如何同时获取一个select 的value和 label值
  • (板子)A* astar算法,AcWing第k短路+八数码 带注释
  • (笔试题)分解质因式
  • (附源码)ssm基于web技术的医务志愿者管理系统 毕业设计 100910
  • (七)Activiti-modeler中文支持
  • (一)appium-desktop定位元素原理
  • .bat文件调用java类的main方法
  • .Net多线程Threading相关详解
  • .net使用excel的cells对象没有value方法——学习.net的Excel工作表问题
  • .NET中GET与SET的用法