我劝!这位年轻人不讲MVCC,耗子尾汁!

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: Hi,大家好!我是白日梦。今天我要跟你分享的话题是:“MySQL是如何根据undo log 链条实现read view机制的?谈谈看”

Hi,大家好!我是白日梦。

今天我要跟你分享的话题是:“MySQL是如何根据undo log 链条实现read view机制的?谈谈看”


一、事务的隔离级别与MVCC?#


MySQL单进程多线程的数据库软件,在事务的并发操作中可能会出现脏读,不可重复读,幻读。


MySQL支持的四种事务隔离级别如下:

  • Read uncommited
    简单来说就是:事务A可以读到事务B未commit的数据。这种情况也被叫做脏读。
  • Read commited
    简单来说就是:事务A可以读到事务B已经commit的数据。
  • Serializable
    在该级别下,写会加写锁、读会加读锁,除了读读不互斥,其他组合都互斥,因此可以保证事务串行化顺序执行,可以避免脏读、不可重复读与幻读。
  • Repeatable read
    如下图:可重复读要求事务A两次 select 查询出来的结果是一样的,即使中间事务B将id=1的行给修改了,也要保证事务A再读取时,读到的结果也得和第一次读到的结果相同。


但是可重复读存在幻读读问题,比如事务A开启后按某个范围X读取一次(事务未提交),这时其他事务在该范围X内插入了新的数据,事务A再读时就会将新插入的数据读取出来,当然在MySQL的RR隔离级别下不会再出现这种幻行的问题。

问题的解决得益于:MVCC多版本并发控制的快照读和next-key lock 当前读。



二、Repeatable Read是如何实现的#


以RR隔离级别为例:


你可以像下面这样看一下你的MySQL默认使用的什么隔离级别:



MVCC多版本并发控制也被称为快照读,在RR的隔离级别下,当事务开启时会创建一个视图(Read View),其实这个视图就是所谓的快照。在整个事务存在的期间,一直会使用这个视图。


下面看一个九个步骤的小实验:



上图中的右部分的会话中begin之后,就会创建读视图,所以它的多次select使用的是同一个视图,所以结果都是一样的。即使数据中途被左边的事务更改了,它也没有受到影响。

再结合视图去理解这个过程。


当你执行begin开启事务之后,MySQL会拍下像下图这样的快照:



上图中的trx_ids中记录着MySQL中活跃的且未提交的事务。

假设有事务A、事务B擦不多在同一时刻开启,那这两个事务会分别得到如下的视图。



在RR的隔离级别下,事务一开启就会得到上图那样的ReadView,并且只要事务不提交这个ReadView就一直有效。

就上图来说:

在事务A的视图中,它的事务ID=61,此时活跃的事务集合是[61、62],活跃的事务ID中最小的事务id是它本身。下一个事务id应该是63。

在事务B的视图中,它的事务ID=621,此时活跃的事务集合是[61、62],活跃的事务ID中最小的事务id是61。下一个事务id应该是63。

先让事务A尝试去读取name列的数据。


它会发现的这行数据的Data_TRX_ID=60,通过和trx_ids对比发现这个事务ID不在活跃的事务id集合trx_ids中,并且小于它本身的60。说明:在事务A开启之前,事务ID=60的事务早就提交过了。所以事务A能直接这行数据name = tom。


然后事务B通过update语句尝试去修改这行数据,想将name 改成 jetty。这时MySQL会记录相应的undo log,并以链表的方式串联起来,于是我们会得到下图:


你可以看到上图中,由于事务B将name改成jerry,导致多出一条undo log。这条undo对应的事务ID=事务B的事务ID = 62。并且通过一个指针执向它的上一个undo log记录。

这时如果事务A重新去读,首先它会读取到的记录是name = jerry,但是它也会发现该记录的trx_id = 62 , 比自己的61还大,并且比下一个事务ID63小。说明:它读到记录其实是和自己同时开启的事务修改后的产物,这时他就会沿着undo log链条往前找,直到找到第一个trx_id等于或者小于自己事务ID的记录为止。所以事务A再一次读取到trx_id = 60的记录。


这也就是所谓的快照读机制。


另外需要注意的是:就上例来说,在RR的隔离级别下,确实能保证事务A每次读取出来的结果都是一样的,而且在事务B将其修改后,事务A依然能读取出name = tom。但是这时name=tom真的只是个快照,本质上它已经可以算是不存在是数据了。




本文是MySQL专题第15篇,全文近100篇(公众号首发)#


本文是第15篇,全文近100篇,点击查看目录




三、Read Commited是如何实现的:#


在RR隔离级别下,当事务一开始视图就会被创建出来,并且一直到该事务提交该视图都有效。


在Read Commited隔离级别,每次select 都会创建一个新的视图。


还是使用这个例子:假设事务A和事务B并发开启,并且各自得到了图中的ReadView。然后很快,事务B就将数据name = tom改成了name = jerry(未提交)。那这时事务A去select会检索出什么结果呢?


事务A检索过程:事务A首先会沿着undo log链条从头开始找,于是它首先找到name = jerry的列。但是它也发现该列的trx_id = 62 不但比自己的事务ID60大,而且还在trx_ids这个活跃事务列表中,说明name = jerry是被和自己差不多同时开启的其他事务更改的。它自然也就读不到。



紧接着事务B提交事务,然后事务A重新select会开启一个新的视图,得到如下图:

当事务A沿着undo log链条往下查找时,他发现首先发现的name = jerry的行的trx_id是62,竟然比自己的事务ID61还大,但是进一步发现,这个事务ID62并不在trx_ids中。说明,这个其实是已经被提交了的数据,那直接就意味着其实自己是允许读出这条数据的。这也就是所谓的读已提交机制。



推荐阅读#


  1. 大家常说的基数是什么?(已发布)
  2. 讲讲什么是慢查!如何监控?如何排查?(已发布)
  3. 对NotNull字段插入Null值有啥现象?(已发布)
  4. 能谈谈 date、datetime、time、timestamp、year的区别吗?(已发布)
  5. 了解数据库的查询缓存和BufferPool吗?谈谈看!(已发布)
  6. 你知道数据库缓冲池中的LRU-List吗?(已发布)
  7. 谈谈数据库缓冲池中的Free-List?(已发布)
  8. 谈谈数据库缓冲池中的Flush-List?(已发布)
  9. 了解脏页刷回磁盘的时机吗?(已发布)
  10. 用十一张图讲清楚,当你CRUD时BufferPool中发生了什么!以及BufferPool的优化!(已发布)
  11. 听说过表空间没?什么是表空间?什么是数据表?(已发布)
  12. 谈谈MySQL的:数据区、数据段、数据页、数据页究竟长什么样?了解数据页分裂吗?谈谈看!(已发布)
  13. 谈谈MySQL的行记录是什么?长啥样?(已发布)
  14. 了解MySQL的行溢出机制吗?(已发布)
  15. 说说fsync这个系统调用吧! (已发布)
  16. 简述undo log、truncate、以及undo log如何帮你回滚事物! (已发布)
  17. 我劝!这位年轻人不讲MVCC,耗子尾汁! (已发布)
  18. MySQL的崩溃恢复到底是怎么回事? (已发布)
  19. MySQL的binlog有啥用?谁写的?在哪里?怎么配置 (已发布)
  20. MySQL的bin log的写入机制 (已发布)


相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
1月前
|
消息中间件 缓存 NoSQL
记一次蚂蚁金服四面遭虐,面试水太深,过河的渡船你造好了吗?
有道无术,术可成;有术无道,止于道;以术识道,以道御术
|
9月前
|
监控 安全 算法
这次锁面试题的连环16问,差点就跪了
这次锁面试题的连环16问,差点就跪了
136 0
|
Web App开发 前端开发 JavaScript
冬奥快结束了还没有抢到冰墩墩?程序员一招让你不用排队不用愁!
随着“2022北京冬奥会”的盛大开幕,冰墩墩的热度与日俱增,线上被抢空,线下排长龙,为购买冰墩墩苦恼的竟少了几根秀发!如今冬奥马上就要拉下帷幕,还没抢到“冰墩墩”不要紧,这款程序来帮忙,国内一位程序员dragonir用前端+建模的方式自己就实现了线上拥有“冰墩墩”,同时将代码开源到了GitHub上,不得不感叹科技的力量,程序员的伟大,让拥有“冰墩墩”变得如此简单!
冬奥快结束了还没有抢到冰墩墩?程序员一招让你不用排队不用愁!
|
存储 缓存 前端开发
表弟面试被虐,我教他缓存连招,借机蹭了波奈雪的茶
表弟面试被虐,我教他缓存连招,借机蹭了波奈雪的茶
表弟面试被虐,我教他缓存连招,借机蹭了波奈雪的茶
J3
|
缓存 安全 Java
volatile,面试前没听过这个那我劝你们,耗子尾汁!!
volatile这个关键字可能很多朋友都听说过,或许也都用过; 在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果。在Java 5之后,volatile关键字才得以重获生机。(下面会说明原因哦!)
J3
97 0
volatile,面试前没听过这个那我劝你们,耗子尾汁!!
|
SQL 安全 前端开发
来来来开小灶了,年后求职和跳槽的看过来,悄悄的看悄悄的收藏
面试官,您好我叫(XXX),今天来公司面试 JAVA开发工程师,之前在(XXX 公司)任职,从事这一行已经有(几)个年头了。这几年开发,主要接触的项目包括(你做过的项目!)等。在开发过程中,也用过好些框架,比如∶ springboot、springcloud、springmvc、spring、Mybatis等技术框架。熟练掌握框架之间的整合技术。有时候因为项目需求或是为了开发的高效性,自己我会研究一些技术,使用一些常用的主流 Java技术,例如∶(吹!用没用过不重要,主要是就是英文的!)。前端的技术也研究过一些。如(原生的、框架啊都往上整!)
171 0
来来来开小灶了,年后求职和跳槽的看过来,悄悄的看悄悄的收藏
|
缓存 NoSQL 安全
(求锤得锤的故事)Redis锁从面试连环炮聊到神仙打架。 (1)
(求锤得锤的故事)Redis锁从面试连环炮聊到神仙打架。 (1)
130 0
|
NoSQL 算法 Java
(求锤得锤的故事)Redis锁从面试连环炮聊到神仙打架。 (2)
(求锤得锤的故事)Redis锁从面试连环炮聊到神仙打架。 (2)
155 0
|
存储 运维 NoSQL
(求锤得锤的故事)Redis锁从面试连环炮聊到神仙打架。 (3)
(求锤得锤的故事)Redis锁从面试连环炮聊到神仙打架。 (3)
124 0
|
前端开发 Java 开发工具
不吹牛,这样的面试官才牛逼!
不吹牛,这样的面试官才牛逼!
110 0
不吹牛,这样的面试官才牛逼!