white-goo
文章7
标签6
分类1
MVCC

MVCC

MVCC就是多版本并发控制,主要处理读请求,而且是快照读

  • 快照读: 就是select查询
  • 当前读: 读取的数据都是最新版本的,会对读取的数据进行加锁,属于悲观锁的一种操作

MVCC是基于undo log加版本链 和 read view去实现的

  • undo log日志: 它记录的是对数据库的操作,除了会保存每次操作的数据,还会有trx_id和roll_pointer字段,trx_id就是事务id,是自增的,roll_pointer是指向上一个版本的回滚指针
  • 版本链: 由undo log日志中的每一天记录通过roll_pointer链接而成的一个链表
  • read view: 是一个快照,其实就是一个对象,用来判断该使用版本链中的哪个版本,有以下属性
    • m_ids: 在生成read view时活跃的事务id,即未提交的事务的id
    • min_trx_id: 在生成read view时最小的活跃的事务id,即m_ids中最小的那个
    • max_trx_id: 在生成read view时,系统应该分配给下一个事务的id
    • creator_trx_id: 表示生成该read view的事务的事务id
  • 判断规则:
    • trx_id == creator_trx_id: 可以访问该版本,表示该条记录是自己创建的
    • trx_id < min_trx_id: 可以访问,表示小于最小的活跃事务id,即该trx_id所对应的事务一定是提交了的
    • trx_id > max_trx_id: 不可以访问,表示该事务id大于系统即将分配的事务id,一定是没有提交的事务
    • min_trx_id <= trx_id <= max_trx_id: 如果trx_id在m_ids中,就不可以访问,不在就行,因为m_ids中的id并不一定是连续的,所以可能或出现已经提交的事务,已提交的事务是可以访问的

MVCC是如何实现不可重复读和可重复读?

其实就是创建read view的时机不同

  • 不可重复读: 每次select,即快照读都会生成一份read view,这样,每次都能读到新的已提交的事务,就实现了不可重复读
  • 可重复读: read view在整个事务期间只会生成一份,这样就不能读取到新提交的事务,就实现了可重复读

值得一提的是,innoDB引擎下,可以通过间隙锁解决幻读问题的,而且innoDB引擎是默认开启间隙锁的

本文作者:white-goo
本文链接:https://white-goo.github.io/2021/08/15/MVCC/
版权声明:本文采用 CC BY-NC-SA 3.0 CN 协议进行许可