MVCC最全详解(定义作用及实现原理)

MVCC最全详解(定义作用及实现原理)-mikechen

什么是MVCC

MVCC全称是Multi Version Concurrency Control,翻译过来就是“多版本并发控制”。

MVCC最全详解(定义作用及实现原理)-mikechen

多版本:多版本就是数据存在多个版本,多个事务在读取和修改时,会根据具体情况读取不同的版本。

并发控制:MVCC是一种并发控制的方法,通过维护一个数据的多个版本,减少读写操作的冲突。

 

MVCC的作用

如果没有MVCC,想要实现同一条数据的并发读写,就需要操作数据加读锁和写锁,这样就降低了数据库的并发性能。

有了MVCC,就相当于把同一份数据生成了多个版本,读写操作互不影响,提高了系统的并发性能。

 

MVCC的实现

MVCC的实现原理,主要是依赖每一行记录中:隐藏字段,undo log,版本链,ReadView。

如下图所示:

MVCC最全详解(定义作用及实现原理)-mikechen

1.隐藏字段

每行记录,除了我们自定义的字段外,还有数据库隐式定义的DB_TRX_ID,DB_ROLL_PTR,DB_ROW_ID等字段。

  • 隐藏主键(DB_ROW_ID):在没有主键时,它会产生聚族索引;
  • 事务ID(DB_TRX_ID):每个事务都会有一个自增的ID,这里记录的是最新的事务ID;
  • 回滚指针(DB_ROLL_PTR):指向这条记录的上一个版本,多个修改会形成一个链表;

如下图所示:

MVCC最全详解(定义作用及实现原理)-mikechen

2.undo log

undo log可以理解成回滚日志,它存储的是老版本数据。

在表记录修改之前,会先把数据拷贝到undo log里,如果事务回滚,即可以通过undo log来还原数据。

可以这样认为,当delete一条记录时undo log 中会记录一条对应的insert记录,当update一条记录时它记录一条对应相反的update记录。

undo日志主要分两种:

  • insert undo log :是在插入时记录的日志,用于回滚操作,提交后日志会被删除。
  • update undo log : 是回滚操作所需要的,快照读取时也需要,在完全不需要时才可能被清理。

Undo log在MVCC中的应用场景主要涉及到读取已提交(Read Committed)和可重复读(Repeatable Read)隔离级别下的事务。

在这些隔离级别下,当一个事务正在修改数据时,其他事务需要读取事务之前的版本,这就涉及到使用undo log来提供一致性的读取。

 

3.版本链

版本链是MVCC实现并发控制的核心概念之一,它通过组织和维护数据的不同版本,为数据库系统提供了高度的并发性和事务隔离性。

比如:多个事务并行操作某一行数据时,不同事务对该行数据的修改会产生多个版本。

然后通过回滚指针(roll_pointer),连成一个链表,这个链表就称为版本链

如下图所示:

MVCC最全详解(定义作用及实现原理)-mikechen

版本链通常由多个版本组成,每个版本包含以下关键信息:

  • 数据值: 版本所对应的实际数据。
  • 版本号(Timestamp): 表示版本的时间戳,用于确定版本在事务时间轴上的位置。
  • 事务ID(Transaction ID): 标识创建该版本的事务。
  • 前一个版本的引用: 指向链中的前一个版本,形成版本链。

版本链在MVCC中是实现并发控制和事务隔离的关键,它使得不同事务可以并发地读取和写入数据,而不会产生读-写或写-写冲突。

 

3.ReadView

如果一个事务要查询行记录,需要读取哪个版本的行记录呢? Read View 就是来解决这个问题的。

比如:当我们用select读取数据时,这一时刻的数据会有很多个版本,但我们并不知道读取哪个版本。

这时就靠readview来对我们进行读取版本的限制,通过readview我们才知道自己能够读取哪个版本。

MVCC最全详解(定义作用及实现原理)-mikechen

ReadView重要的属性,如下:

  • trx_ids: 当前系统中那些活跃(未提交)的读写事务ID, 它数据结构为一个List。
  • low_limit_id: 目前出现过的最大的事务ID 1,即下一个将被分配的事务ID。
  • up_limit_id: 活跃事务列表trx_ids中最小的事务ID,如果trx_ids为空,则up_limit_id 为 low_limit_id。
  • creator_trx_id: 表示生成该 ReadView 的事务的 事务id。

如何查询一条记录

主要包含如下5大步骤:

  1. 获取事务自己的版本号,即 事务ID;
  2. 获取 Read View;
  3. 查询得到的数据,然后 Read View 中的事务版本号进行比较;
  4. 如果不符合 ReadView 规则, 那么就需要 UndoLog 中历史快照;
  5. 最后返回符合规则的数据。

MVCC多版本控制就是通过 :ReadView UndoLog 实现的,UndoLog 保存了历史快照,ReadView 规则帮助判断当前版本的数据是否可见。

 

MVCC的总结

MVCC是一种高效的并发控制机制,通过版本管理实现了对数据的并发访问和事务隔离。

它提供了更高的并发性能和更好的隔离级别,但也带来了一些额外的存储开销和实现复杂性。

在处理大量并发事务的数据库系统中,MVCC是一种常见且有效的并发控制策略。

mikechen

mikechen睿哥,10年+大厂架构经验,资深技术专家,就职于阿里巴巴、淘宝、百度等一线互联网大厂。

关注「mikechen」公众号,获取更多技术干货!

后台回复架构即可获取《阿里架构师进阶专题全部合集》,后台回复面试即可获取《史上最全阿里Java面试题总结

评论交流
    说说你的看法