MySQL-理解 MVCC 原理

299 阅读4分钟

默认的 MySQL 隔离级别是 RR ( Repeatable Read ), 而 MySQL 底层通过 MVCC 机制 实现了 RR ,并且解决了 一部分的幻读问题,今天我们来深入理解一下 MySQL 底层是如何实现 MVCC 的。

MVCC

MVCC (Multiversion Concurrency Control) 也就是 多版本并发版本控制,简单点来说就是 多个事务查询同一批数据时只能查看到当前事务可查看的数据。

MVCC 主要通过 undolog 版本链 和 readview 来完成,以下来逐一说明一下 它们的用处

UndoLog 版本链

首先说明一个前置知识点,其实每一条数据都有了两个隐藏字段(其实不止两个), 一个是 trx_id , 一个是 roll_pointer。

  • trx_id: 最近更新这条数据的事务id
  • roll_pointer:指向更新这个事务之前生成的 undolog

MySQL 在执行每一个操作之前,会先插入一条 undolog ,如果是 insert 则插入 delete ,如果是 update ,则将 update 之前的数据插入 undolog,以此达到 回滚的目的。 那 undolog 的数据中,还会有一个额外的字段,那就是 事务版本号(trx_id),这个版本号是递增的,随着事务数量的增多,版本号也会越来越大。由此也能组成一个 undolog 的版本链。

Pasted image 20240831134306.png

而有了事务版本链,也就能解决一个简单的问题,也就是 当前事务,只看当前事务的数据,不会看到别的事务的数据。但它还没办法解决 ,可重复阅读的问题。例如,事务A 查询了 id=1 的数据,这时候 事务B来了,修改了 id=1的数据,并提交了。这时候 事务A 应该查看到 事务B 最新提交的数据吗? 在 RR 的隔离级别下,是不应该的,而这个问题单靠 UndoLog 版本链是无法很好的解决的,这时候就需要 ReadView 出马了。

ReadView

在 MySQL中在事务执行第一个SELECT语句时都会生成一个 ReadVIew,ReadView 中包含 四个字段

  • m_ids(trx_ids):当前激活的事务ids
  • low_limit_id: 当前激活的事务中最小的id
  • up_limit_id:下一个事务id,也就是最大的事务id
  • creator_trx_id:当前的事务id 而这个 ReadView 生成以后 就不会再进行改变了。

假设

  1. 有一条数据 id=1,age=18,trx_id=1
  2. 首先 事务A 进来了 它的ReadView 是 { m_ids:[ ], min_trx_id:2, max_trx_id:3,creator_trx_id:2 } -> 这表示当前除了它自己并没有其他的活跃事务, 表明它可以查看 trx_id 小于等于 2 的数据。
  3. 然后 事务B 进来了 它的ReadView 是 { m_ids:[ 2 ], min_trx_id:2, max_trx_id:4,creator_trx_id:3 } -> 这表示当前已有1个活跃事务 [ 2 ] , 这时候它可以查看 trx_id 小于等于 3 且事务id不包含在 m_ids 中的数据。

这时候,事务B 将 数据修改为 age=19 ,那么 此时数据就变成 id=1,age=18,trx_id=3 。 若事务A 查询,则会发现 这个 trx_id 不满足它的查看要求,则会向上搜索 undoLog 版本链,最终找到原始数据 id=1,age=18,trx_id=1 并返回。

  1. 这时候 事务C 进来了 它的ReadView 是 { m_ids:[ 2,3 ], min_trx_id:2, max_trx_id:5,creator_trx_id:4 } -> 这表示当前已有2个活跃事务 [ 2,3] ,则表示 它可以查看 trx_id 小于等于 4且事务id不包含在 m_ids 中的数据。 若事务C要查询,则会发现 这条数据的 trx_id:3 在自己的 m_ids列表中,表示这是当前活跃事务的数据,则不会采用这条数据,会向上搜索 undoLog 版本链,最终找到原始数据 id=1,age=18,trx_id=1 并返回。

Pasted image 20240831172203.png

RC 是如何实现的

说完了RR下的MVCC,可以顺带说一下 RC 下的 MVCC 是怎么样的。在RC隔离级别下,事务的每次查询都会生成一次 ReadView,这样就可以实现每次在事务提交后 ,查询到最新事务的数据了。


以上就是 MySQL 的MVCC 的基本原理,通过 undoLog 版本链 和 ReadView 便可方便快捷的在多事务环境下保证数据的安全性。