在 MySQL 的 InnoDB 中,即使事务尚未分配事务 ID,读视图(Read View) 的生成仍然依赖于系统中的活跃事务列表。这是通过 MVCC 的机制来实现的,以下是具体的原理和可见性判断方法。
MVCC 的核心概念
在 MVCC 中,每一行记录都有两个隐藏的版本控制字段:
trx_id
(事务 ID):记录最后修改该行的事务 ID。roll_pointer
:指向 Undo Log 的指针,用于回溯到上一版本数据。
活跃事务列表
当一个事务开始并生成 Read View
时,InnoDB 会获取当前系统中活跃事务的快照,包括:
min_trx_id
:系统中仍未提交的最小事务 ID。max_trx_id
:系统中尚未分配的下一个事务 ID(逻辑上的"最大事务 ID")。- 活跃事务集合 (
active_trx_ids
):当前系统中所有未提交的事务 ID 列表。
这些信息被保存为 Read View
,决定了当前事务能够看到的数据版本。
没有事务 ID 的事务如何判断可见性
即使事务没有分配事务 ID(例如纯读事务),Read View
的生成机制依然可以运作,具体如下:
可见性规则
对于每一行记录的 trx_id
(记录最后修改该行的事务 ID),Read View
会通过以下规则判断该行是否可见:
-
当前事务的写入是否可见:
- 如果
trx_id
小于min_trx_id
:表示该事务在当前事务启动之前已经提交,因此该版本是可见的。 - 如果
trx_id
大于或等于max_trx_id
:表示该版本是未来的修改版本,对当前事务不可见。
- 如果
-
当前事务的并发写入是否可见:
- 如果
trx_id
在[min_trx_id, max_trx_id)
区间内:- 检查
active_trx_ids
中是否包含该trx_id
。 - 如果包含,表示该事务仍未提交,对当前事务不可见。
- 如果不包含,表示该事务已经提交,该版本是可见的。
- 检查
- 如果
事务未分配事务 ID 的特殊处理
对于未分配事务 ID 的事务:
- 它的
Read View
的创建仅依赖系统中的活跃事务列表 (active_trx_ids
)。 - 判断可见性时,当前事务没有事务 ID,因此不会参与
active_trx_ids
的比较,完全基于其他事务的状态来判断可见性。
这种设计确保了即使是纯读事务,也能通过 Read View
保证一致性。
总结
即使事务没有分配事务 ID,它的 Read View
是基于快照生成的,使用以下机制判断数据版本的可见性:
- 通过
trx_id
与min_trx_id
和max_trx_id
的比较。 - 通过
active_trx_ids
判断未提交的并发事务。 这套机制确保了任何事务都能正确判断数据的可见性,无论事务是否分配了事务 ID。