Mysql日志篇(MVCC)

89 阅读4分钟

多版本并发控制 (MVCC)

MVCC 是一种在高并发环境下实现事务隔离的技术,它允许读取数据的事务访问“快照”,而不阻塞其他事务的写入操作。

作用

实现读写分离:

  1. 读取事务可以看到某个数据的历史版本。
  2. 写入事务对数据进行修改时创建新版本,不影响读取事务。

MVCC 的核心机制

  • 隐藏列
    1. trx_id(事务id):记录最近一次对该行执行修改的事务 ID。
    2. roll_pointer(版本链指针,指向undolog的地址):指向 Undo Log,保存之前的版本数据。
  • 快照读
    1. 对于非锁定的 SELECT 语句(如 SELECT ...),MVCC 提供一致性视图(Read View)。
    2. 根据当前事务的快照,从 Undo Log 中获取符合事务隔离级别的数据。
  • 当前读
    1. 对于锁定的读操作(如 SELECT ... FOR UPDATE),直接读取最新的数据版本,同时加锁防止其他事务修改。

Read View(一致性视图)

Read View 是它根据事务的活跃状态和 Undo Log 提供历史数据支持。

在事务隔离级别为 读提交(READ COMMITTED) 或 可重复读(REPEATABLE READ) 时,Read View 确定了当前事务能够看到的数据版本。

它可以通过回溯数据行的 Undo Log,读取事务开始时可见的历史数据版本。

Read View 的核心组成

  • m_ids(活跃事务列表):创建 Read View 时,当前系统中所有活跃事务的事务 ID 列表。表示这些事务尚未提交,其修改对当前事务不可见。
  • min_trx_id(最小活跃事务 ID):m_ids 中事务 ID 的最小值。表示当前系统中未提交事务的最小事务 ID。
  • max_trx_id(最大事务 ID):表示创建 Read View 时,系统中已经分配的下一个事务 ID。 当前事务只能看到事务 ID 小于 max_trx_id 的提交内容。
  • creator_trx_id(当前事务 ID):当前事务自身的事务 ID。

Read View 的可见性规则

  • 事务 ID 小于 min_trx_id:该事务已经提交,其修改对当前事务可见。
  • 事务 ID 大于或等于 max_trx_id:该事务尚未启动,其修改对当前事务不可见。
  • 事务 ID 在 [min_trx_id, max_trx_id) 范围内: 如果事务 ID 在 m_ids 中,表示该事务仍在活跃状态,其修改对当前事务不可见。 如果事务 ID 不在 m_ids 中,表示该事务已提交,其修改对当前事务可见。

Read View如何工作

假设有如下事务:

  1. 事务 A(trx_id=101):启动后,修改一条记录并未提交。
  2. 事务 B(trx_id=102):启动并读取相同记录。

事务 A 修改后的记录如下(修改前的数据值='第一个事务'):

ID数据值trx_idroll_pointer
1新值101指向 Undo Log(旧值)

事务 B 的 Read View

  • m_ids = {101}(事务 A 未提交)。
  • min_trx_id = 101。(m_ids中的最小事务id)
  • max_trx_id = 103(事务 B 的下一个事务 ID)。
  • creator_trx_id = 102。(当前事务id)

事务 B 读取时

  • 数据行的 trx_id=101 在 m_ids 中,因此不可见。
  • 根据 roll_pointer 回溯到 Undo Log,获取旧版本数据,最终读取到旧值="第一个事务"。

Read View 在不同隔离级别中的表现

  • 读未提交:不依赖Read View, 每次都读取最新的值。
  • 读提交(READ COMMITTED):每次读取数据都会创建新的 Read View。事务能看到其他事务已经提交的最新修改。
  • 可重复读(REPEATABLE READ):在事务启动时创建一次 Read View,并在整个事务生命周期内保持不变。确保事务多次读取相同数据时,结果一致。(比如事务A未提交、之后的创建的事务B、C提交后,依然不可见)
  • 串行化(SERIALIZABLE):不依赖 Read View,而是通过加锁确保事务串行执行。

ReadView优点与局限性

  • 优点:高效并发;读写分离,读操作不会阻塞写操作。一致性,通过 Read View,确保事务读取到一致的数据快照。
  • 局限性: 存储开销, Undo Log 的历史数据需要占用额外存储。长事务问题:长时间运行的事务会导致大量 Undo Log 堆积,增加存储和回收压力。