Read View在MVCC里如何工作的

困难只是暂时的,放弃才是永久的。
—— 罗伯特·舒勒

我们需要了解两个知识:

  • Read View中四个字段作用;
  • 聚簇索引记录中两个跟事务有关的隐藏列;

那 Read View 到底是个什么东西?

Read View 有四个重要字段:

  • m_ids : 指的是在创建Read View时,当前数据库中 活跃事务 的 事务id列表,注意是一个列表, 活跃事务 指的就是,启动了但还没提交的事务
  • min_trx_id : 指的是在创建Read View 时,当前数据库中 活跃事务 中事务id最小的事务,也就是m_ids的最小值。
  • max_trx_id : 这个并不是m_ids的最大值,而是创建Read View时当前数据库中应该给下一个事务的id值,也就是全局事务中最大的事务id值 + 1。
  • creator_trx_id : 指的是创建该Read View 的事务的事务id

知道了Read View 的字段,我们还需要了解聚簇索引记录中的两个隐藏列。

对于使用InnoDB存储引擎的数据库表,他的聚簇索引记录中都包含下面两个隐藏列:

  • trx_id: 当一个事务对某条聚簇索引记录进行改动时,就会把该事务的事务id记录在trx_id隐藏列里
  • roll_ pointer:每次对某条聚簇索引记录进行改动时,都会把旧版本的记录写入到undo日志中,然后这个隐藏列是个指针,指向每一个旧版本记录,于是就可以通过它找到修改前的记录。

在创建Read View后,我们可以将记录中的trx_id划分这三种情况:

一个事务去访问记录的时候,除了自己的更新记录总是可见之外,还有这几种情况:

  1. 如果记录的trx_id值小于Read View中的 min_trx_id 值,表示这个版本的记录是在创建Read View已经提交的事务生成的,所以该版本的记录对当前事务 可见
  2. 如果记录的trx_id值大于等于Read View中的 max_trx_id 值,表示这个版本的记录是在创建Read View才能启动的事务生成的,所以该版本的记录对当前事务 不可见
  3. 如果记录的trx_id 值在 Read View的min_trx_idmax_trx_id之间,需要判断trx_id是否在m_ids列表中:
    • 如果记录的trx_id m_ids列表中,表示生成该版本记录的活跃事务依然活跃着(还没提交事务),所以该版本的记录对当前事务不可见
    • 如果记录的trx_id 不在 m_ids列表中,表示生成该版本记录的活跃事务以及被提交,所以该版本的记录对当前事务 可见

这种通过 版本链 来控制并发事务访问同一个记录时的行为就叫MVCC(多版本并发控制)

原文

posted @ 2025-04-04 15:24  Tsukinor  阅读(42)  评论(0)    收藏  举报