MVCC(多版本并发控制)是 PostgreSQL 系数据库并发能力的基石。但具体到「某个事务能不能看到某条数据」这个最基础的问题,答案藏在元组版本链、事务快照和隔离级别的交叉判定逻辑里。本文完整拆解 HaishanDB 的元组可见性判定机制。
HaishanDB 依靠元组多版本序列与当前事务快照两套数据,结合事务隔离级别规则,完成元组数据可见性判定。下面先交代核心数据来源和判定流程,再逐一拆解所有场景。一、前置基础
1. 核心数据来源每条逻辑数据会产生多条物理元组版本,形成版本链表。
例如:数据项 Q 的版本序列 Q930、Q931、Q932、Q933、Q934,其中数字 93* 代表生成该元组的事务 ID。可见性判定主要提取元组核心字段:字段含义xmin创建该元组的事务 IDxmax删除/更新该元组的事务 IDcmin / cmax事务内的命令序号同时结合对应事务的提交、终止状态进行综合判断。事务快照(snapshot)是另一套关键数据。
当前事务执行查询操作时会生成专属快照,核心字段包括:字段含义xmin快照中事务 ID 下限(小于此值的事务均已提交)xmax快照中事务 ID 上限(大于等于此值的事务尚未开始)xip活跃事务 ID 数组(快照生成时正在运行的事务)快照主要用于区分不同事务的执行时序、判定事务是否完成提交,是多版本可见性比对的核心依据。
2. 判定整体流程
第一步:提取目标数据的完整元组版本序列,批量获取每条元组的 xmin、xmax、cmin、cmax 字段及对应事务运行状态。
第二步:获取当前事务的快照信息,依托快照核心字段,界定创建/修改元组的事务与当前事务的时序关系。
第三步:结合数据库不同事务隔离级别对应的可见性规则,完成元组对当前事务是否可见的最终判定。
3. 核心判定思路
设定待判定元组为 tuple,当前事务快照为 snapshot。整体判定逻辑:基于元组自身 {xmin, xmax} 事务区间,与快照 {xmin, xip, xmax} 事务区间进行范围匹配,枚举所有可能的交集场景,结合事务隔离级别规则,逐一判定各场景下元组的可见性状态。
二、分场景可见性判定完整规则
以下将所有可能的可见性判定场景逐一展开,每个场景给出判定结论和逻辑依据。
场景 1:xmin 事务未提交,且异常终止元组对应的创建事务未正常完成提交,数据有效性不成立。结论:不可见。
场景 2:xmin 事务未提交,且由当前事务/父子事务生成此场景下,结合元组生成命令与快照生成的时序关系、元组 xmax 标记状态,分为 6 个子场景。
子场景 2.1:生成元组的命令晚于快照生成当前事务生成快照时,该元组尚未创建。结论:不可见。
子场景 2.2:生成命令早于快照;xmax 仅锁定、无更新当前事务可正常读取自身写入的未更新数据。结论:可见。
子场景 2.3:生成命令早于快照;xmax 标记多事务更新(multi)三种情况分别判定:情况结论删除/更新事务不是当前事务可见(规避脏读)更新事务为当前事务,且更新命令在快照生成后可见更新事务为当前事务,且更新命令在快照生成前不可见
子场景 2.4:生成命令早于快照;xmax 被非当前事务/异常父子事务删除终止状态的父子事务统一归类为非当前事务。删除事务已异常终止,元组数据未被有效删除。结论:可见。
子场景 2.5:生成命令早于快照;xmax 被当前事务删除,删除命令晚于快照生成快照生成时刻,该元组尚未执行删除操作,数据有效。结论:可见。
子场景 2.6:生成命令早于快照;xmax 被当前事务删除,删除命令早于快照生成快照生成时刻,该元组已完成删除操作,数据失效。结论:不可见。
场景 3:xmin 事务未提交,非当前事务/父子事务创建外部未提交事务的 ID 必然大于快照 xmin。结合快照活跃事务状态分为两个子场景:
子场景 3.1:xmin 存在于快照 xip 活跃事务数组受事务隔离级别约束,当前事务无法读取其他事务未提交数据。结论:不可见。
子场景 3.2:xmin 大于快照 xmax当前事务生成快照时,该元组的创建事务尚未启动,元组不存在。结论:不可见。
场景 4:xmin 事务已提交(xmin < 快照 xmin)元组创建事务已完成提交,数据初始化有效。根据 xmax 标记的更新/删除事务状态,细分为 5 个子场景。
子场景 4.1:xmax 无效(无更新、无删除)元组无任何后续修改、删除操作,为当前有效最新版本。结论:可见。
子场景 4.2:xmax 仅锁定、未执行更新元组仅被锁定,无实际数据变更,数据保持有效。结论:可见。
子场景 4.3:xmax 标记多事务更新五种情况分别判定:情况结论更新事务为当前事务,更新命令在快照后可见更新事务为当前事务,更新命令在快照前不可见更新事务非当前事务,xmax 在快照 xip 内(未提交)可见更新事务非当前事务,xmax 事务已提交不可见更新事务非当前事务,xmax 事务异常终止可见
子场景 4.4:xmax 标记更新事务尚未提交四种情况分别判定:情况结论更新事务为当前事务,更新命令在快照后可见更新事务为当前事务,更新命令在快照前不可见更新事务非当前事务,xmax 在快照 xip 内(未提交)可见更新事务非当前事务,xmax 事务未提交可见
子场景 4.5:xmax 标记更新事务已提交该元组已被其他事务更新并固化为有效数据,当前元组为过期版本。结论:不可见。总结HaishanDB 的 MVCC 元组可见性判定可以归纳为一套规则:1.先看 xmin:创建元组的事务是否已提交?未提交且非当前事务 → 不可见2.再看 xmax:是否有后续事务删除/更新了该元组?无操作或仅锁定 → 可见3.交叉比对时序:xmax 的更新事务与当前快照的时序关系决定了在「更新已发生但未提交」这类临界场景下的最终可见性这套判定逻辑覆盖了事务隔离级别的核心语义,理解它才能真正搞懂 HaishanDB 的并发行为。 #haishanDB #海山数据库 #He3DB