深入原理分析MYSQL的MVCC并发控制

如果觉得文章还不错的话,欢迎关注我的个人微信公众号!

乐享Coding

MVCC【多版本并发控制】

优势

不加锁,提升并发事务下的性能,实现读写可以并发。

三大核心

  • ReadView
  • undolog
  • 隐藏字段
隐藏字段
事务ID

Innodb引擎向每行记录增加的字段,6字节,记录增删改操作的一个事务的唯一标识,逐渐递增的。也是MVCC作为比对决定是否可见的值。

回退指针

指向更新删除前一个版本的地址指针,多次修改会生成一个版本链。

undolog

增删改mysql数据前,会在修改之前的版本的数据加上隐藏字段记录到undolog日志中,事务执行失败后可以回滚。

ReadView

某一时刻的事务快照,RC和RR隔离级别下ReadView的生成时机不同。

主要有以下核心属性

  • 最大ID(已创建的最大事务ID)
  • 最小ID(执行查询时所有未提交事务中最小的事务ID)
  • 创建视图时的活跃事务ID列表(未提交的事务在数组中)

image-20210913205319400

回顾事务的隔离级别
  • 读未提交(Read Uncommitted):最低的隔离级别,会读取到其他事务还未提交的内容,存在脏读。
  • 读已提交(Read Committed):读取到的内容都是已经提交的,可以解决脏读,但是存在不可重复读。
  • 可重复读(Repeatable Read):在一个事务中多次读取时看到相同的内容,可以解决不可重复读,但是存在幻读。但是在 InnoDB 中不存在幻读问题,对于快照读,InnoDB 使用 MVCC 解决幻读,对于当前读,InnoDB 通过 gap locks 或 next-key locks 解决幻读。
  • 串行化(Serializable):最高的隔离级别,串行的执行事务,没有并发事务问题
MVCC主要实现RC和RR隔离级别

Mysql 8.0修改隔离级别的命令如下

SET [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE}

注意:需提前关闭事务的自动提交

set autocommit = [0|1]   // 0 是关闭 1 是开启

实战案例

RR(可重复读隔离级别下MVCC的原理)

当我们的隔离级别为 RR 时:每开启一个事务,系统会给该事务会分配一个事务 Id,在该事务执行第一个 select 语句的时候,会生成一个当前时间点的事务快照 ReadView

RR隔离级别3

RC(读已提交隔离级别下MVCC的原理)

RC 级别在该事务执行中每次 select 时,都会生成一个 ReadView。

RC隔离级别

总结

注意以下几点

  • ReadView仅仅是一个视图,里面仅包含几个变量。

  • 对于删除操作,仅仅是复制了上一个版本链并加了一个删除标记,MVCC比对事务id时看到该标记代表该数据不存在不会从返回数据。

  • 事务id比较规则

    1. 如果落在(trx_id < min_id)黄色区域,证明这个版本是已提交的事务生成的,可见。
    2. 如果落在(trx_id < min_id)红色区域,证明这个版本是将来启动的事务生成的,不可见。

    如果落在蓝色部分(min_id <= trx_id <= max_id)

    • 若row的trx_id在数组中,表示这个版本是还没提交的事务生成,不可见。
    • 若row的trx_id不在数组中,表示这个版本已经提交了的事务生成的,可见。
MVCC 解决了幻读了没有?

MVCC 解决了部分幻读,但并没有完全解决幻读。

对于快照读,MVCC 因为因为从 ReadView 读取,所以必然不会看到新插入的行,所以天然就解决了幻读的问题。

而对于当前读的幻读,MVCC 是无法解决的。需要使用 Gap Lock 或 Next-Key Lock(Gap Lock + Record Lock)来解决。

其实原理也很简单,用上面的例子稍微修改下以触发当前读:select * from user where id < 10 for update,当使用了 Gap Lock 时,Gap 锁会锁住 id < 10 的整个范围,因此其他事务无法插入 id < 10 的数据,从而防止了幻读。

Repeatable Read 解决了幻读是什么情况?

Gap Lock 时,Gap 锁会锁住 id < 10 的整个范围,因此其他事务无法插入 id < 10 的数据,从而防止了幻读。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Steve_hanhaiLong

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值