MySQL 的 MVCC 原理详解

什么是 MVCC ?
  • mvcc,全称 multi-version concurrency control,即多版本并发控制
  • mvcc 是 mysql 的 innodb 引擎为了解决读写冲突,通过不加锁的方式而实现的一种解决冲突的处理方式

为什么需要 MVCC ?
  • 数据库原生的锁
    • 最原生的锁,锁住一个资源后会禁止其他任何线程访问同一个资源,但是很多应用的一个特点都是读多写少的场景,很多数据的读取次数远大于修改的次数,而读取数据间互相排斥显得不是很必要

  • 读写锁
    • 读锁和读锁之间不互斥,而写锁和写锁、读锁都互斥,这样就提升系统的并发能力,之后发现并发读还是不够

  • mvcc
    • 读写之间也不冲突的方法,读取数据时通过快照的方式将数据保存下来,这样读锁就和写锁不冲突,不同的事务 session 会看到特定版本的数据,快照是一种概念模型,不同的数据库可能用不同的方式来实现这种功能

MVCC 适用于的事务隔离级别
  • mvcc 只在 read_committed、repeatable_read 两个隔离级别下工作
  • 其他两个隔离级别够和 mvcc 不兼容,因为 read_uncommitted 总是读取最新的数据行, 而不是符合当前事务版本的数据行,而 serializable 会对所有读取的行都加锁

MVCC 实现原理
  • 实现原理依赖记录中的 3个隐式字段,undo日志 ,read view 来实现
    • 隐式字段
      • DB_TRX_ID:记录最近更新这条记录的事物id,大小为 6 个字节
      • DB_ROLL_PTR:是一个回滚指针,用于配合 undo日志,指向上一个旧版本,大小为 7 个字节
      • DB_ROW_ID:数据库默认为该行记录生成的唯一隐式主键,大小为 6 个字节(表没有主键会生成)

  • 业务场景
    请添加图片描述
  • 基于 undo_log 生成的版本链:

  • Read View 是一个数据结构,包含 4 个字段
    • m_ids:当前活跃的事务编号集合
    • min_trx_id:最小活跃事务编号
    • max_trx_ id:预分配事务编号,当前最大事务编号 + 1
    • creator_trx_id:read view 创建者的事务编号

  • 这个业务场景生成的 Read View
    • m_ids = (2,3,4)
    • min_trx_id = 2
    • max_trx_id = 5
    • creator_trx_id = 4

  • 版本链数据访问规则:
    • 版本链的最新事物id 值为 3,就是当前的事物id
    • 判断当前事务id 是否等于 creator_trx_id(4),等于说明数据就是自己这个事务更改的,可以访问
    • 判断 trx_id < min_trx_id(2),成立说明数据已经提交,可以访问
    • 判断 trx_ id > max_trx_id(5),成立说明该事务是在 readview 生成以后才开启,不允许访问
    • 判断 min_trx_id(2) <= trx_id <= max_ trx_id(5),成立在 m_ids 数据中对比,不存在则代表数据是已提交的,可以访问
    • 比较流程:
      • 当前事物id 为 3,不是 creator_trx_id(4),也不 < min_trx_id(2),但是在事物id 范围内
      • 事物id 为 3 无法访问,就基于 undo_log 向上寻找到事物id 为 2,找到事物id 为 2 的进行比较,不是 creator_trx_id(4),也不 < min_trx_id(2),但是在事物id 范围内
      • 事物id 为 2 也无法访问,基于 undo_log 向上寻找到事物id 为 1,符合 < min_trx_id(2),可以访问数据
    • 因此根据 readview 可以读取到1号事务提交的数据:张三

  • 不同隔离级别下的 MVCC
    • read_committed:在读已提交的隔离级别下,每次快照读都是生成最新的 readview,所以在上述场景中,事物4 第二次读取数据的时候,事物2 已提交了事物,所以在事物4 中出现了不可重复读
    • repeatable_read:在可重复读的隔离级别下,readview 读取数据会沿用当前事物第一次生成的 readview,所以不会出现不可重复读的情况

参考资料
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

tytler

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

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

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

打赏作者

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

抵扣说明:

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

余额充值