Mysql MVCC

什么是MVCC

MVCC是一个常用于数据库管理系统的并发控制方法,能提供对数据库的并发访问

在没有并发控制的情况下,如果有人在读取数据的同时,另外有人在修改数据。那么读者可能看到一段写一半或者不一致数据。

MVCC则旨在通过保留数据项的多个副本来解决问题。当MVCC数据库需要更新数据时,不会用新数据覆盖原数据,而是创建该数据的新版本。每个事务看到的版本取决于隔离级别。

常见一个例子就是修改博客后常常需要审核,在审核通过之前,会将未修改过的旧版本给读者看,当通过之后就给最新版本看

MVCC应用场景为一个事务读,另一个事务写这种情况。

InnoDB 隐藏字段

InnoDB为每一行加入以下3个字段

  • 6 bytes DB_TRX_ID表示上一个插入或者更新这行的事务ID。顺便,删除也被认为更新,因为在内部是通过更新一个特殊的bit来表明这行被删除了,后面交给purge线程去自动删除
  • 7 bytes DB_ROLL_PTR表示回滚指针。当一个事务对一条数据更改之后,都会将旧版本数据放到Undo-log日志中,而 DB_ROLL_PTR就会指向Undo-log中旧版本数据,当需要回滚事务时,就可以通过该列去回滚
  • 6 bytes DB_ROW_ID表示当主键、唯一非空字段都不存在的时候,就会隐定义一个顺序递增的列来作为聚簇索引列,只是索引无法上层使用,只能让InnoDB构建树结构储存表数据

Undo-log日志

undo-log是单个读写事务关联的undo log记录集合。在事务没有提交前,会先将记录更新前数据到undo log

ReadView

ReadView是一个事务在尝试读取一条数据时,MVCC基于当前MySQL运行状态生成的快照

当事务启动后首次执行select时,会生成一个数据库当前的ReadView

  • creator_trx_id: 代表创建该ReadView的事务ID
  • trx_ids: 表示生成当前ReadView时,系统内活跃的事务ID列表
  • up_limit_id: 最小的活跃事务id
  • low_limit_id: 表示生成当前ReadView时,要给下一个事务分配的ID

不同级别下的MVCC

在read committed级别下,MVCC会在每次select前生成一个ReadView,所以就会在第二次查询中读取到修改后的数据

在read repeatable级别下,只会在首次select时生成ReadView,解决了不可重复读问题

工作流程

  1. 事务出现select时,生成ReadView
  2. 判断行数据trx_id是否与该事务id一致,若一致,则读取最新数据
  3. 判断行trx_id是否小于readView最小活跃事务ID,若小于,则说明在事务创建ReadView之前就已经结束,那么也可以读取最新数据
  4. 判断行trx_id是否小于ReadView下一个要分配的事务ID,若大于等于,则说明是ReadView之后才修改的,那么便不能访问最新数据
  5. 判断行trx_id是否在ReadView正在执行的事务中,若在则不能访问最新数据;否则能访问最新数据

那么获取哪个版本的旧数据呢?

首先根据roll_ptr找到链表头,然后遍历不在ReadView活跃事务中的旧数据

范围查询时出现突增数据怎么办?

新增数据的roll_ptr为Null,那么便无法在旧版本中找到数据,也就意味对事务不可见,查询结果也不会出现这条数据

启示

  • 避免大事务。长运行事务不仅会占用连接,还会迫使数据库更长时间保存历史。如果该事务正在读取大量数据,随后写入会迫使该事务读取回滚日志
  • 避免一次写入大量数据。每次写都会生成一个事务ID和相应的undo log,并且会造成次级索引的混乱。
  • 经常更新的counter将强制更多行事务ID更新和撤销日志项。如果可能的话,提前批处理这些更新,或者考虑储存到单独表中,以便在需要时加入

Ref

  1. https://en.wikipedia.org/wiki/Multiversion_concurrency_control
  2. https://juejin.cn/post/7155359629050904584
  3. https://dev.mysql.com/doc/refman/8.0/en/innodb-multi-versioning.html
  4. https://medium.com/@ajones1_999/understanding-mysql-multiversion-concurrency-control-6b52f1bd5b7e
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值