MySQL InnoDB的MVCC实现机制

article/2025/9/15 11:59:36

MySQL InnoDB的MVCC实现机制

  • 1.MVCC概述
  • 2.MVCC的实现原理
    • 隐式字段
    • undo日志
    • Read View(读视图)
    • RR隔离级别的Read View方案

1.MVCC概述

什么是MVCC?

MVCC,即多版本并发控制。MVCC是一种并发控制的方法,一般在数据库管理系统中,实现对数据库的并发访问,在编程语言中实现事务内存

MVCC在MySQL InnoDB中的实现主要是为了提高数据库并发性能,用更好的方式去处理读-写冲突,做到即使有读写冲突时,也能做到不加锁,非阻塞并发读

什么是当前读和快照读?

  • 当前读
    select lock in share mode(共享锁), select for update ; update, insert ,delete(排他锁)这些操作都是一种当前读,就是它读取的是记录的最新版本,读取时还要保证其他并发事务不能修改当前记录,会对读取的记录进行加锁
  • 快照读
    像不加锁的select操作就是快照读,即不加锁的非阻塞读,快照读的实现是基于多版本并发控制,即MVCC,可以认为MVCC是行锁的一个变种,但它在很多情况下,避免了加锁操作,降低了开销;既然是基于多版本,即快照读可能读到的并不一定是数据的最新版本,而有可能是之前的历史版本

说白了MVCC就是为了实现读-写冲突不加锁,而这个读指的就是快照读, 而非当前读,当前读实际上是一种加锁的操作,是悲观锁的实现😯

总之,MVCC就是因为大牛们,不满意只让数据库采用悲观锁这样性能不佳的形式去解决读-写冲突问题,而提出的解决方案,所以在数据库中,因为有了MVCC,所以我们可以形成两个组合:

  • MVCC + 悲观锁 MVCC解决读写冲突,悲观锁解决写写冲突
  • MVCC + 乐观锁 MVCC解决读写冲突,乐观锁解决写写冲突

这种组合的方式就可以最大程度的提高数据库并发性能,并解决读写冲突,和写写冲突导致的问题!


2.MVCC的实现原理

它的实现原理主要是依赖记录中的 4个隐式字段,undo日志 ,Read View 来实现的😪

隐式字段

每行记录除了我们自定义的字段外,还有数据库隐式定义的DB_TRX_ID,DB_ROLL_PTR,DB_ROW_ID等字段

  1. DB_ROW_ID 6byte, 隐含的自增ID(隐藏主键),如果数据表没有主键,InnoDB会自动以DB_ROW_ID产生一个聚簇索引
  2. DB_TRX_ID 6byte, 最近修改(修改/插入)事务ID:记录创建这条记录/最后一次修改该记录的事务
  3. IDDB_ROLL_PTR 7byte, 回滚指针,指向这条记录的上一个版本(存储于rollback segment里)
  4. DELETED_BIT 1byte, 记录被更新或删除,并不代表真的删除,而是删除flag变了

在这里插入图片描述

DB_ROW_ID是数据库默认为该行记录生成的唯一隐式主键;DB_TRX_ID是当前操作该记录的事务ID;而DB_ROLL_PTR是一个回滚指针,用于配合undo日志,指向上一个旧版本;delete flag没有展示出来😫

undo日志

InnoDB把这些为了回滚而记录的这些东西称之为undo log。这里需要注意的一点是,由于查询操作(SELECT)并不会修改任何用户记录,所以在查询操作执行时,并不需要记录相应的undo log。undo log主要分为3种:

  • Insert undo log :插入一条记录时,至少要把这条记录的主键值记下来,之后回滚的时候只需要把这个主键值对应的记录删掉就好了。
  • Update undo log:修改一条记录时,至少要把修改这条记录前的旧值都记录下来,这样之后回滚时再把这条记录更新为旧值就好了。
  • Delete undo log:删除一条记录时,至少要把这条记录中的内容都记下来,这样之后回滚时再把由这些内容组成的记录插入到表中就好了。

删除操作都只是设置一下老记录的DELETED_BIT,并不真正将过时的记录删除🥱

对MVCC有帮助的实质是update undo log ,undo log实际上就是存在rollback segment中旧记录链,它的执行流程如下:

  1. 比如一个有个事务插入persion表插入了一条新记录,记录如下,name为Jerry, age为24岁,隐式主键是1,事务ID和回滚指针,我们假设为NULL
    在这里插入图片描述
    在这里插入图片描述
  2. 现在来了一个事务1对该记录的name做出了修改,改为Tom
  • 在事务1修改该行(记录)数据时,数据库会先对该行加排他锁
  • 然后把该行数据拷贝到undo log中,作为旧记录,即在undo log中有当前行的拷贝副本
  • 拷贝完毕后,修改该行name为Tom,并且修改隐藏字段的事务ID为当前事务1的ID, 我们默认从1开始,之后递增,回滚指针指向拷贝到undo log的副本记录,即表示我的上一个版本就是它
  • 事务提交后,释放锁
    在这里插入图片描述
  1. 又来了个事务2修改person表的同一个记录,将age修改为30岁
  • 在事务2修改该行数据时,数据库也先为该行加锁
  • 然后把该行数据拷贝到undo log中,作为旧记录,发现该行记录已经有undo log了,那么最新的旧数据作为链表的表头,插在该行记录的undo log最前面
  • 修改该行age为30岁,并且修改隐藏字段的事务ID为当前事务2的ID, 那就是2,回滚指针指向刚刚拷贝到undo log的副本记录
  • 事务提交,释放锁
    在这里插入图片描述

同事务或者相同事务的对同一记录的修改,会导致该记录的undo log成为一条记录版本线性表,即链表,undo log的链首就是最新的旧记录,链尾就是最早的旧记录

Read View(读视图)

Read View主要是用来做可见性判断的, 即当我们某个事务执行快照读的时候,对该记录创建一个Read View读视图,把它比作条件用来判断当前事务能够看到哪个版本的数据,即可能是当前最新的数据,也有可能是该行记录的undo log里面的某个版本的数据。

Read View遵循一个可见性算法,主要是将要被修改的数据的最新记录中的DB_TRX_ID(即当前事务ID)取出来,与系统当前其他活跃事务的ID去对比(由Read View维护),如果DB_TRX_ID跟Read View的属性做了某些比较,不符合可见性,那就通过DB_ROLL_PTR回滚指针去取出Undo Log中的DB_TRX_ID再比较,即遍历链表的DB_TRX_ID(从链首到链尾,即从最近的一次修改查起),直到找到满足特定条件的DB_TRX_ID, 那么这个DB_TRX_ID所在的旧记录就是当前事务能看见的最新老版本

上述语言可能难以理解,我们来看下面几张图来辅助一下理解:

首先,Read View维护的视图到底是怎样的?(这里以RC隔离级别举例)

在这里插入图片描述

首先,

  • m_ids为当前系统正在活跃的事务列表(即事务没有被提交)
  • min_trx_id为活跃事务列表的最小值(即开启时间最靠前的一个事务)
  • max_trx_id为活跃事务列表的最大值(即开启时间最靠后的一个事务)
  • create_trx_id为当前快照读所在的事务

那么这个判断条件是什么呢?

很简单

在这里插入图片描述

RR隔离级别的Read View方案

RR隔离级别解决可重复读的问题,本质上是通过对Read View视图的复用来实现的😴

在这里插入图片描述

也就是说,对于在一个事务中不同的快照读,共享一个最早的Read View视图,以保证数据的一致性!


http://chatgpt.dhexx.cn/article/6qGZqsfH.shtml

相关文章

MVCC原理以及隔离机制

1、mysql是如何进行数据回滚的 mysql使用了大量的 undo日志、trx_id 字段以及 roll_pointer 字段来实现的数据回滚。版本链比对规则图: 查询 ​ 当mysql开启一个查询时 遇到的select语句会创建一个 read-view 一致性视图,这个视图里面保存 一个未提交…

【MVCC多版本并发控制】MVCC 机制的原理及实现,什么是MVCC,多版本并发控制

什么是 MVCC MVCC (Multiversion Concurrency Control) 中文全程叫多版本并发控制,是现代数据库(包括 MySQL、Oracle、PostgreSQL 等)引擎实现中常用的处理读写冲突的手段,目的在于提高数据库高并发场景下的吞吐性能。 如此一来…

MySql的MVCC实现机制

MVCC实现机制 快照读和当前读MVCC 快照读和当前读 在了解MySql的MVCC实现之前,需要先了解什么是快照读和当前读,以便于后续讲解 快照读:就是单纯的 SELECT 语句,不包括下面这两类语句: SELECT ... FOR UPDATE SELECT ... LOCK I…

MVCC机制略解

在mysql中,默认的隔离级别是可重复读。即在一个事物中读取到的数据总是一样的,即使其他事务把数据改了,那在这个事务中读取的数据还是第一次读取的数据。 mysql还可以设置为读已提交隔离级别。即一个事务中读取的数据,随着其他事务…

什么是MVCC,一文搞懂MySQL的MVCC机制

MVCC是什么 MVCC,即Multi-Version Concurrency Control (多版本并发控制)。它是一种并发控制的方法,一般在数据库管理系统中,实现对数据库的并发访问,在编程语言中实现事务内存。 数据库中同时存在多个版本…

对MVCC全面解析

简介 MVCC(Multi-Version Concurrency Control)即多版本并发控制。 MVCC的实现原理 我们在了解MVCC之前,首先先了解一下几个比较常见的锁。 读锁:也叫共享锁、S锁,若事务T对数据对象A加上S锁,则事务T可…

【MySQL】MVCC机制

什么是MVCC MVCC 英文全称:Multi-Version Concurrency Control,Mysql的事务隔离性就是主要靠MVCC机制来实现的。对一行数据的读和写默认是不会通过加锁互斥来保证隔离性的,这样避免了频繁的加锁互斥,而在串行化隔离级别为了保证较…

一文精通MVCC机制

MVCC(Multi-Version Concurrency Control)多版本并发控制机制 使用串行化隔离级别时,mysql会将所有的操作加锁互斥,来保证并发安全。这种方式必然降低并发性能。mysql在读已提交和可重复读隔离级别下,对一行数据的读和写两个操作默认是不会通…

数据库的MVCC机制

MVCC 1. 什么是MVCC MVCC (Multiversion Concurrency Control),多版本并发控制。顾名思义,MVCC 是通过数据行的多个版 本管理来实现数据库的 并发控制 。这项技术使得在InnoDB的事务隔离级别下执行 一致性读 操作有了保 证。换言…

MySQL之MVCC机制

1. MVCC概念 MVCC,全称Multi-Version Concurrency Control,即多版本并发控制。MVCC是一种并发控制的方法,一般在数据库管理系统中,实现对数据库的并发访问,在编程语言中实现事务内存。 在Mysql的InnoDB引擎中就是指在…

【MySQL进阶-05】深入理解mvcc机制(详解)

MySql系列整体栏目 内容链接地址【一】深入理解mysql索引本质https://blog.csdn.net/zhenghuishengq/article/details/121027025【二】深入理解mysql索引优化以及explain关键字https://blog.csdn.net/zhenghuishengq/article/details/124552080【三】深入理解mysql的索引分类&a…

MVCC及实现原理

!首先声明,MySQL 的测试环境是 5.7 前提概要 什么是 MVCC什么是当前读和快照读?当前读,快照读和 MVCC 的关系MVCC 实现原理 隐式字段undo日志Read View整体流程MVCC 相关问题 RR 是如何在 RC 级的基础上解决不可重复读的&#xf…

4gl程式debug常用技巧

1、带参数的D: ‘MISC’表示具体料号传入 2、指定行数设置断点 比如我要在程式axmt360中的211行开始D 进入Debug界面后按ctrlD 弹出界面 输入b 行数 点OK 出现上面表示已设置OK,然后点cancel或叉叉退出 最后点下面按扭,程式跑到210行时自…

【OpenGL】十五、OpenGL 绘制三角形 ( 绘制 GL_TRIANGLE_FAN 三角形扇 )

文章目录 一、绘制 GL_TRIANGLE_FAN 三角形1、绘制 3 个点的情况2、绘制 4 个点的情况3、绘制 5 个点的情况4、绘制 6 个点的情况 二、相关资源 一、绘制 GL_TRIANGLE_FAN 三角形 GL_TRIANGLE_FAN 的绘制规则是 , 以第 1 1 1 个点作为顶点 , 第 1 , 2 , 3 1,2,3 1,2,3 个点组…

Unity3D笔记十八 GL图像库

作者:PEPE 出处:http://pepe.cnblogs.com/ 1、绘制2D图像的时需要使用GL.LoadOrtho()方法来将图形映射到平面中。 2、所有绘制相关的内容都要写在OnPostRender()方法中。 3、有关GL图像库的脚本需要绑定到Hierarchy视图中Camera上,否则无法…

Mapbox GL插件之echartsLayer

Mapbox GL除了本身的api具有的功能以外,还能够集成各种开源的类库。 ECharts 是一个使用 JavaScript 实现的开源可视化库,涵盖各行业图表,百度公司开发的,同时其中也有一些地图的效果。 Mapbox GL的echarts插件,在gith…

【OpenGL】十八、OpenGL 绘制多边形 ( 绘制 GL_POLYGON 模式多边形 )

文章目录 一、绘制 GL_POLYGON 模式多边形二、多边形绘制顺序分析三、相关资源 一、绘制 GL_POLYGON 模式多边形 使用 glBegin(GL_POLYGON) 设置绘制多边形 , 不管有几个点 , 都按照指定的顺序连接起来 ; 注意 : 这些点组成的多边形必须是凸多边形 , 不能是凹多边形 ; 代码示例…

gl_FragCoord 的含义

gl_FragCoord 表示当前片元着色器处理的候选片元窗口相对坐标信息,是一个 vec4 类型的变量 (x, y, z, 1/w), 其中 x, y 是当前片元的窗口坐标,OpenGL 默认以窗口左下角为原点, 在 着色器中通过布局限定符可以重新设定原点&#xf…

WebGL着色器内置变量gl_PointSize、gl_Position、gl_FragColor、gl_FragCoord、gl_PointCoord

WebGL着色器内置变量 WebGL中文教程网 本文是WebGL教程(电子书)的2.7节内容 着色器语言在GPU的着色器单元执行,javascript语言、C语言在CPU上执行,任何一种语言的语法规则,整体设计都和它执行的硬件有一定的关系,GPU和CPU执行程…

Unity画线之GL

上一篇中,SetPixel的方法,卡顿严重,暂未解决,又去看了原来的GL画线,自己画图思考了一下适配UI的问题,最终解决。 特此说明,GL画线功能,及Shader均为借鉴,自己做了优化。…