mysql详情之MVCC由浅入深

news2024/11/25 12:45:09

概念

MVCC(Multiversion Concurrency Control):多版本并发控制。是一种并发控制的方法,一般在数据库管理系统中,实现对数据库的并发访问。

MVCC的实现思路

  1. 修改数据时,都对应一个修改者所属的事务【前提条件】

  2. 每个事务都有自己的事务编号【前提条件】

  3. 每条数据里都有个隐藏字段,可以用来存修改者事务编号【前提条件】

  4. 每次修改时,保留原数据,产生一条新版本数据。并且在新数据里的隐藏字段存上修改者事务编号A【前提条件】

  5. 当另一个事务B要去访问那个数据时,就可以根据访问者的事务编号B去判断并选取哪个版本的数据【实现MVCC】

  6. 至于怎么选取,还有一个“场外配置项”来控制:隔离级别【配置】

至此我们就知道了MVCC基本原理。

mysql实现的MVCC逻辑

见文章Mysql的MVCC的理解(这篇文章简洁而逻辑清晰,就不重复了)

这里就着重讲解以下几点

四种隔离级别

  • RU(READ UNCOMMITTED)读未提交
  • RC(READ COMMITTED)读已提交
  • RR(REPEATABLE READ)可重复读
  • SERIALIZABLE 串行化

版本链:就是用来把各个版本的数据连起来,保存起来。供访问者从新到旧的顺序筛选,直到找到自己能看的数据

ReadView:一个非常重要且比较难理解的概念。表示当前活跃的事务id列表(已开始,还未提交),这是个静态数据,生成了就不再变。

根据我们前面说的mvcc基本原理。大致的朴素设想:隔离级别应该是用来控制算法走向的。

但mysql的实现更加巧妙。算法中用到了ReadView这个数据,隔离级别是用来控制ReadView的。实现了算法不变,算法用到的数据根据配置改变(优美的代码结构)

逻辑场景:ReadView是访问者产生的。每次访问数据,访问者自己就生成一个ReadView,拿在手里。然后去版本链里筛选数据。

隔离级别的控制方式:RC的时候,是整个事务里,每次select都会重新产生一个ReadView。RR的时候,是访问者第一次select时生成了ReadView,整个事务里一直用它(虽然RR的隔离级别更高,但相对来说实现起来反而更简单,更快。默认用这个级别大概也有层意思)。

注意:上面的“select”指的是“select 同一张表”(RC时,即便两次单独查不同行,也会使用同一个ReadView。但查不同表就一定是两个ReadView)。

实验

这是一个很经典的观察ReadView生成逻辑的简单实验。

实验材料

  1. MySql5.7

  2. 一个表,名叫staff。字段:id | name | age | pos | salary

操作:开两个命令行窗口,都打开msql命令行窗口,分别开两个事务A,B;A读 B改数据

目标:观察一个可能会被误解的现象(如果懂了上面的原理,就很容易理解了)

前提

  1. 关掉事务自动提交 set global autocommit=0;

  2. 保持mysql的默认隔离级别RR不要动

实验1(命令前的数字代表操作顺序号)

事务A事务B
1. begin; 【开始事务A】2. begin;【开始事务B】
3. select * from staff;【观察到:id为3的age=20】
4. update staff set age=30 where id=3;
5. commit;【结束事务B】
6. select * from staff;【观察到:id为3的age=20】

这个现象很好理解,符合我们心中RR的印象:一个事务里,查询到的数据不变,所以事务A感知不到B对数据的修改。

实验2(对照组)

事务A事务B
1. begin; 【开始事务A】2. begin;【开始事务B】
3. update staff set age=40 where id=3;
4. commit;【结束事务B】
5. select * from staff;【观察到:id为3的age=40】
6. commit;【结束事务A】

这个现象就可能不太符合我们对RR的理解了。事务A居然感知到B对数据的变化了。

实际上这是我们对RR的误解,RR的本意是:可重复读。即在一个事务里,无论读多少次都一样。并没有规定读到的是什么数据。

如果不了解原理,可能会觉得很神奇,甚至有点“量子力学”到感觉:是否观察居然影响到了结果。

实验2中之所以能读到事务B修改的数据,那是因为事务A在步骤5时才第一次生生成ReadView。

如果要验证RC的情况,就先改一下配置隔离级别:
//设置read uncommitted级别:
set session transaction isolation level read uncommitted;

//设置read committed级别:
set session transaction isolation level read committed;

//设置repeatable read级别:
set session transaction isolation level repeatable read;

//设置serializable级别:
set session transaction isolation level serializable;

如果要验证:“select”指的是“select 同一张表”。可以把两个select * from staff;换成不同的表,换成单独查两行,都是可以验证的。

至此,你已经理解mysql实现mvcc的关键原理。

深入细节

有了前面的铺垫,可以再看这篇文章(MySQL中MVCC的正确打开方式(源码佐证)),就不会有太大难度了。没啥可强调的,其实就是上面关键原理的具体实现代码层面。有兴趣的可以看看。

MVCC和二级索引

上面我们讲的数据版本链,都是数据行上的操作。那如果远离数据行的二级索引被改了,肯定也要读写并行。那么是怎么实现的?

其实上二级索引应对多版本问题,只简单实现了一小部分。当自己无法判断处理时,就先取出来,最后还是交给数据行的mvcc机制决定这条数据是否符合。具体实现方式:

  • 给每个索引都加一个隐藏字段(最后修改的事务ID)。再加一个索引链,用来挂改之前的老数据。
  • 修改索引字段时,不是直接改,而是新增一个索引数据,然后把老数据挂在索引链上。
  • 查询的时候,如果原来是判断等于xx = 数据,那么此时的判断逻辑就相当于变成了 xx in(新数据, 老数据1,老数据2)。如果查出来符合,但此时的数据还不能直接返回给用户,还需要根据主键找到具体数据行,最后根据上面mvcc的原理决定是否返回给用户。

具体看博客(mysql二级索引没有mvcc_MySQL InnoDB MVCC深度分析),或者直接看官网(Clustered and Secondary Indexes)。
这里你可能会产生的疑惑:二级索引的判断如何跟聚簇索引保持一致的?(二级索引可以不完全判断一个数据的可见性,但不能跟聚簇索引判断出来的结果矛盾。就像基层员工由于没经验,可以不完全知道怎么处理一件事,但他不能告诉客户一个跟领导完全相悖的答案)
他们能保证不出现自相矛盾的方法,靠的就是数据访问者手里的那个ReadView,这是二级索引和聚簇索引共同使用的判断数据版本的依据。

这里我发现一个很有意思的事情。以前我总觉得看不懂官网是自己英文太差。但实际上,可以看看这篇文章(原封不动翻译的官网文章)。如果不是看了前面那篇博客,这一坨中文同样让人看不懂。

其他

undo log到底是什么

前面我们说版本链的时候,说版本链是有各个版本的数据串起来的链。其实这个说法不准确。这串起来的其实是undo log。并不是数据行。

在学习redo log,undo log的时候,就会强调:redo log是物理日志,undo log是逻辑日志。undo log可以简单理解为sql语句。
通过这样的sql语句 和 新版数据 就可以得到上一个版本的老数据(减少空间浪费)。

快照读,当前读

在学mvcc时,还会“莫名其妙”的提到快照读,当前读这两个词。之所以说莫名其妙,因为粗看这两个词的功能,似乎和mvcc并没有很强的功能上的关联。你可能还会听到一致性非锁定读这个词,更觉得有点晕。

其实快照读就是非锁定读(Nonlocking Reads),当前读就是锁定读(Locking Reads)。我觉得还是直译为锁定读/非锁定读更直观好理解。因为这两个词直接区分的就是是否用锁。

无论是否用锁,我们都希望读到的数据不要受外界(其他写操作)干扰,变来变去。所以就加了个一致性。怎么实现一致性呢? 加锁的很好理解,隔离级别为串行化时,就是通过加锁,读写完全串行化,但性能很差。那不加锁呢?就是通过这里的主角MVCC机制实现。

由于锁定读肯定是一致的,所以在看官网时,目录:一个叫“Consistent Nonlocking Reads”,一个叫“Locking Reads”(把一致性直接省略了)。这也是为什么你听过“一致性非锁定读”这个词,但没见过“一致性锁定读”这种说法。
事实上:mysql官网里,一致读(Consistent Read)就特指MVCC的在RC/RR两种隔离级别的情况。

乐观锁?

有人说MVCC是一种乐观锁的实现。这种说法是不对的
数据库中的乐观锁指的是两个写操作之间的实现方式。改的时候不加锁,先查版本号(也可根据自己的业务情况,设计其他类型的唯一字段),保存时根据版本号判断是否要保存(CAS机制),如果已经有其他写操作已经把版本号改了,那就保存不了。

select version from table;--得到oldV
update table set col=newData, vesion=(oldV + 1) where version=oldV and 其他条件;

乐观锁是用户自己根据业务场景,自己实现的CAS机制(比如实现在多线程或集群下对资源的抢占。一种简易的分布式锁)。mysql并没有这种乐观锁机制。

普通select

包括官网里,在说普通select的时候,其实指的都是包含在事务里的普通select语句。不要误以为直接操作数据库,写了一句select就是普通select。不加事务的select,查询只能读到提交后的数据,和mvcc机制没有关系。看下面这个图

在这里插入图片描述

一致性

这个词很容易让人误解。我觉得根源在于中文里没有一个独立且合适的简单词汇来代表“一贯不变”。一致一致性 是两个看似一样,但意思却很不同的词,前者单纯的表示“一样”,后者是英文Consistent的翻译(一贯不变)。

在计算机行业里,即便是同样都用一致性,意思也会有细微差别。数据库里的一致性一致性hash也不太一样。前者指的是一个事物在经过一些列操作之后依然得到正确的结果。后者强调的是多个个体之间(横向),在一段时间里(纵向)表现都一致。这种细微的含义差别,英文里也没有区分,都用的是Consistent

总结

  • MVCC是为实现隔离性的一种无锁方案。
  • 相比有锁方案,实现了读写并行处理,提高了系统性能。
  • 实现机制是多版本控制

参考

面试官:谈谈你对Mysql的MVCC的理解?

MySQL中MVCC的正确打开方式(源码佐证)

MySQL事务日志(redo log和undo log)的详细分析

mysql二级索引没有mvcc_MySQL InnoDB MVCC深度分析

Clustered and Secondary Indexes

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

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

相关文章

统计学习方法 | 朴素贝叶斯

朴素贝叶斯法是基于贝叶斯定理与特征条件独立假设的分类方法 对于给定的训练数据集,首先基于特征条件独立假设学习输入 / 输出的联合概率分布;然后基于此模型,对给定的输入x,利用贝叶斯定理求出后验概率最大的输出y 朴素贝叶斯法…

数据结构---无序数组排序后的最大相邻差

无序数组排序后的最大相邻差先排序,在一个一个求差,找出最大的差解法2(计数排序变体)第一步第二步第三步第四步例子JAVA实现解法3(桶排序变体)第一步第二步第三步例子JAVA实现有一个无序整型数组,如何求出该数组排序后的任意两个相邻元素的最…

洛谷千题详解 | P1022 [NOIP2000 普及组] 计算器的改良【C++、Python、Java语言】

博主主页:Yu仙笙 专栏地址:洛谷千题详解 目录 题目背景 题目描述 输入格式 输出格式 输入输出样例 解析: C源码: Python源码: Java源码: ---------------------------------------------------------------…

前端基础_绘制带边框矩形

绘制带边框矩形 今天给小伙伴分享,如何在canvas画布中绘制一个矩形。在本例中调用了脚本文件中的draw函数进行图形描绘。该函数放置在body属性中,使用“οnlοad"draw(canvas);"”语句,调用脚本文件中的draw函数进行图像描画。在本…

大数据组件之Flink

文章目录大数据组件之Flink一.Flink简介Flink是什么?Flink的特点Flink框架处理流程Flink发展时间线Flink在企业中的应用Flink的应用场景为什么选择Flink?传统数据处理架构有状态的流式处理(第一代流式处理架构)流处理的演变&#…

实锤了,尤大妥妥的二次元迷弟 —— 聊聊 Vue 的进化历程

文章目录实锤了,尤大妥妥的二次元迷弟 —— 聊聊 Vue 的进化历程1. 前言2. 库阶段2.1 阶段发展2.2 设计重点和特征3. 框架阶段3.1 阶段发展3.2 设计重点4. 通用框架阶段4.1 阶段发展4.2 设计重点4.3 典型案例5. 编译/运行时混合阶段5.1 阶段发展5.2 设计重点5.3 框架…

五十二——六十二

五十二、JavaScript——函数简介 一、函数 函数(Function)- 函数也是一个对象 - 它具有其他对象所有的功能 - 函数中可以储存代码,且可以在需要时调用这些代码 语法: function 函数名(){ 语句。。。 } 调用函数- 调用…

drm框架介绍

Drm框架介绍 DRM是Linux目前主流的图形显示框架,相比FB架构,DRM更能适应当前日益更新的显示硬件。比如FB原生不支持多层合成,不支持VSYNC,不支持DMA-BUF,不支持异步更新,不支持fence机制等,而这…

嗅探网站视频

前置知识 MP4是我们常见的视频格式,往往我们在播放服务器视频时直接就是请求的MP4视频源。但其实这样并不好,MP4头文件[ftypmoov]较大,初始化的播放需要下载完整的头文件并进行解析,之后再下载一定长度的可播视频片段才能进行播放…

java 瑞吉外卖day4及补全功能 文件上传下载 菜品分页查询 Dto类 菜品状态修改 菜品停售以及菜品删除

文件上传下载 文件下载介绍 文件上传代码实现 服务端上传: RestController RequestMapping("/common") Slf4j public class CommonController {Value("${reggie.path}")private String basePath;//从配置文件读取设置好的basePathPostMapping…

【教程】5步免费白嫖使用Grammarly Premium高级版

转载请注明出处:小锋学长生活大爆炸[xfxuezhang.cn] 1、使用Chrome或者Edge浏览器。 2、安装名为Cookie-Editor的谷歌Chrome扩展。 https://chrome.google.com/webstore/detail/cookie-editor/hlkenndednhfkekhgcdicdfddnkalmdm 2、打开Grammarly网站,…

DBCO-PEG-Cyanine5.5,CY5.5 PEG DBCO,二苯并环辛炔-聚乙二醇-Cyanine5.5

中文名:二苯并环辛炔-聚乙二醇-菁染料CY5.5,二苯并环辛炔-聚乙二醇-Cyanine5.5,菁染料CY5.5PEG环辛炔,花青素Cyanine5.5-聚乙二醇-二苯并环辛炔英文名:DBCO-PEG-CY5.5,DBCO-PEG-Cyanine5.5,Cyan…

位运算、递推与递归、前缀和、差分、二分

题目链接:位运算、递推与递归、前缀和、差分、二分 - Virtual Judge (vjudge.net) A.洛谷 - P2280 样例输入: 2 1 0 0 1 1 1 1样例输出: 1 分析:这道题先用二维前缀和处理一下地图,这样我们就可以在O(1)的复杂度内…

SIT-board 远程交互式白板的实现

来自上海应用技术大学的「SIT-board」团队,在七牛云校园黑客马拉松中勇夺冠军,以下是他们的参赛作品——SIT-board远程交互白板的实现过程。 需求分析 基本绘图功能 作为一个在线协作白板,离线的本地化的白板是一切功能的前提。本地白板中需…

Uniapp安卓apk原生云端打包完整过程

1.进入HbuliderX,找到菜单的发行 2.选择原生App-云打包,接着会弹出一个对话框,如图: 3.在对话框中勾选Andriod(apk包)、选择使用云端证书。 证书说明如下: (1)使用自有证书:开发者自己生成…

左偏树解决猴王问题

一 问题描述 在森林里住着 N 只好斗的猴子。开始时,猴子们彼此不认识,难免吵架,吵架只发生在互不认识的两只猴子之间。吵架发生时,两只猴子都会邀请它们中最强壮的朋友来决斗。决斗过后,两只猴子和它们的所有朋友都认…

screenviewer工具在树莓派3B+上的适配

目录 工具简介 适配初衷 第三方模块适配问题 源码代编译问题 最后完美运行如图 工具简介 屏幕截图web端展示功能、视频设备如摄像头、视频流等接入,并可web端展示。 适配初衷 这样的工具如果能完美运行在嵌入式linux上是极好的,目前仅适配了wind…

为什么你的程序跑不满CPU?——简单聊聊多核多线程

最近同事测试自己的程序,感觉处理耗时太长,一看CPU使用率,才25%。想要提高CPU使用率降低处理时长,于是向我询问。以此为契机写了这篇,聊聊多核多线程。水平有限,仅供参考。 1.单核单线程 一切开始的前提是…

CCProxy + Proxifier 通过另一台电脑访问网络

问题场景描述: 公司提供的 vpn 只提供了 windows 客户端;Mac没有客户端,而家里的 windows 电脑是多年前的旧电脑,配置不足,所以不能使用;这里整理了一种 搭建跳板机 作为中专的方式进行访问 搭建过程 1.…

OpenCV(7)-OpenCV中的滤波器

OpenCV中的滤波器 图像滤波 滤波的作用:一幅图像通过滤波器得到另一幅图像;其中滤波器又称为卷积核,滤波的过程被称为卷积 卷积的几个基本概念: 卷积核的大小: 卷积核一般为奇数,如3 * 3,5 * 5&#xf…