前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Mysql专题|如果早知道MVCC可以这样学,我也不至于被面试官虐的这么惨!

Mysql专题|如果早知道MVCC可以这样学,我也不至于被面试官虐的这么惨!

作者头像
AI码师
发布2022-09-19 12:01:28
3670
发布2022-09-19 12:01:28
举报

什么是MVCC?

MVCC是Multi-Version Concurrency Control(多版本并发控制)的缩写。

MVCC解决了什么问题?

图片来自网络

我们知道在mysql中有四种事务隔离级别:读未提交、读已提交、可重复读和串行读。在四种隔离级别中,可重复读就是通过MVCC实现的。通过MVCC,能够保证在事务开启后,保证每次读取的数据都是一样的;但是却不能解决幻读的问题,庆幸的是mysql使用间隙锁解决了在可重复读级别下出现的幻读问题。

MVCC实现原理

MVCC主要是借助mysql的undo log和一致性视图(快照)来实现。

undo log 记录了数据在变迁过程中所关联的事务ID;

一致性视图(快照)保存了线程在开启一个事务之后,数据的一个快照点,记录当前事务的状态。

那么MVCC是如何通过undolog 和一致性视图来实现可重复读的呢?

首先我们思考这样一个问题,在可重复读模式下,开启一个事务之后会是什么样的场景:

  • 能看到本事务开启前的所有已经提交的事务产生的数据
  • 不能看到未提交的事务产生的数据

假设每个事务都有自己的事务ID,并且这个id是递增的,后创建的事务ID大于先创建的事务ID

所以如果想要实现这样一个场景,开启事务后,需要保存以下两个数据状态:

  • 未提交的事务作为一个数组 un_commit[],按顺序排列
  • 生成一个下一个即将分配的事务ID MAX_ID

准备工作做好以后,我们先介绍下mysql在新增、删除和修改数据的时候,mysql底层是如何存储的

mysql 如何记录我们增删改的数据?

mysql在底层为undolog 中每条数据都会增加三个伪字段字段:创建事务ID,是否删除标记(默认否),上一版本指针

数据记录是按照数据更新时间从上往下排的,这里为了书写方便,更换了排列顺序,请注意区分

  • 初始结构

Id

Name

txc_id

是否删除

上一版本指针

1

yang

100

False

  • 修改 name= zhang

Id

Name

txc_id

是否删除

上一版本指针

1

yang

100

False

1

zhang

200

False

地址1

  • 新增id=2

Id

Name

txc_id

是否删除

上一版本指针

1

yang

100

False

1

zhang

200

False

地址1

2

lisi

300

False

  • 删除id=2

Id

Name

txc_id

是否删除

上一版本指针

1

yang

100

False

1

zhang

200

False

地址1

2

lisi

300

False

2

lisi

400

true

地址2

不管新增删除还是修改,都是复制一份数据,而不是在原有数据上操作,这样最终就会形成一个数据链,很适合做快照。

通过上面的描述,大家应该对mysql如何通过undolog存储我们的数据链有了一个大概的认识,现在我们回归正题:MVCC是如何通过undolog 来查找我们的数据,实现可重复读呢?

MVCC是如何查询我们想要的数据,保证可重复读呢?

在前面已经提到过,mysql在开启事务后,会生成一个一致性视图,其实对于程序来说就是记录当前的数据点:

  • 未提交的事务做一个数组 un_commit[],按顺序排列
  • 生成一个下次即将分配的事务ID MAX_ID

ok,现在我们利用这两组数据,来查找id为1的数据

假设当前分配的事务ID为300,目前有两个未提交的事务[100,200],我们现在模拟下查找流程

初始状态

Id

Name

txc_id

是否删除

上一版本指针

1

yang

50

False

A开启事务后,第一次查找

执行了第一条select语句时,系统分配了一个事务ID 300,此时有两个未提交的事务100,200,目前是想要查找id为1的记录

  • 比较第一条,提取创建事务id=50,比较后发现创建事务id小于当前事务ID=300,进入下一步
  • 判断 创建事务id小于最小的未提交事务id=100,则可以认为当前这条数据是在本事务开启之前就已经提交了,所以返回此条数据。
  • 查找完成
此时事务ID=100的修改了id=1 的数据,并且提交了事务

此时的数据长这样:

Id

Name

txc_id

是否删除

上一版本指针

1

zhang

100

False

地址1

1

yang

50

False

A事务此时进行第二次查找

从上往下找

  • 提取第一条数据,判断发现创建事务id=100是小于当前事务ID=300,则进入下一个判断
  • 判断发现事务id=100 是在 未提交数组[100,200]中,所以对当前事务事务是不可见的,进入下一个判断
  • 提取上一个版本指针的地址,定位到数据
  • 比较发现当前数据创建的事务id是50,小于最小的未提交事务的id,所以返回此条数据
此时事务ID=200的删除了id=1 的数据,没有提交事务

此时数据长这样:

Id

Name

txc_id

是否删除

上一版本指针

1

zhang

200

true

地址2

1

zhang

100

False

地址1

1

yang

50

False

A事务此时进行第二次查找

此次查找过程和上面一样,最终定位到事务id=50时产生的数据记录

A事务进行了update操作后,会更新数据视图

未提交数组:[200],当前预分配的事务ID=400

A开启事务后,进行第一次查询

生成数据视图保存点:未提交数组:[200],当前预分配的事务ID=400

  • 从第一条开始比较,发现事务Id=200在 未提交事务的数组中,则根据地址2找到下面一条记录
  • 创建事务id=100 小于最小的未提交事务id=200,则返回此条数据。

注意:在所有查找过程中,匹配到最终可见的数据后,还需要判断数据的删除标记为是否已经标记为删除状态,如果标记为删除状态,则不返回此条数据,并且终止向下查询!!!

福利大放送

关注微信公众号“AI码师”,领取2021最新面试资料和最新全套微服务教程

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-06-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 乐哥聊编程 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 什么是MVCC?
  • MVCC解决了什么问题?
  • MVCC实现原理
    • 那么MVCC是如何通过undolog 和一致性视图来实现可重复读的呢?
      • mysql 如何记录我们增删改的数据?
      • MVCC是如何查询我们想要的数据,保证可重复读呢?
  • 福利大放送
相关产品与服务
云数据库 SQL Server
腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档