postgresql xmin xmax cmin cmax ctid

它们是 PostgreSQL 中最常被查询的五个系统列。它们都是隐式定义的(无需手动声明),始终存在(除了 tableoid 在某些分区情况下),并且 不会 被 SELECT * 返回 ------ 必须显式指定列名。

它们实现了 MVCC(多版本并发控制)、行版本管理、可见性规则和物理行寻址。

快速汇总表

列名 类型 大小 用途 / 含义 典型值 / 备注
xmin xid 4 字节 创建/插入此版本行的事务 ID 行的"诞生"事务。对于大多数快照,其可见性始于该事务提交之时。MVCC 的核心。
xmax xid 4 字节 删除/更新(使失效)此行版本的事务 ID 0 = 行仍存活(尚未被删除或更新)。非 0 = 行已死或被 UPDATE 取代(新版本已存在)。可能暂时持有多事务锁 ID。
cmin cid 4 字节 在插入事务内的命令 ID 事务内的哪个语句/命令创建了这个版本。对于简单事务通常为 0。用于 事务内部可见性。
cmax cid 4 字节 在删除事务内的命令 ID,如果未删除则为 0 事务内的哪个语句使此行失效。对存活的行则为 0。cmin/cmax 在元组头中共用同一个存储槽位(重叠)。
ctid tid 6 字节 此行版本的物理位置:(块号, 块内元组索引) "行指针"。UPDATE 或 VACUUM FULL 时会改变。用于 HOT 链(在同一页面上指向新版本的前向指针)。可用作物理定位器(但不稳定)。

可见性规则(MVCC 的核心)

PostgreSQL 根据 快照 结合这些字段,决定一个行版本对你的 事务 是否可见:

行版本可见的条件(简化版,基于"读已提交"/"可重复读"规则):

  1. xmin 已提交 且 xmin ≤ 快照的水平线

  2. 并且
    xmax = 0 或
    xmax 正在进行中 或
    xmax > 快照的水平线 或
    xmax 已中止/回滚

事务内部可见性 (同一事务能看到自身的更改)还会用到 cmin/cmax 和命令序列。

  • 在 读已提交 级别:每个语句获取新快照 → 能在事务中途看到其他并发提交的更改。

  • 在 可重复读 / 可序列化 级别:在第一个语句处获取快照 → 在整个事务期间保持稳定的视图。

实践示例

复制代码
-- 查看它们(它们对 SELECT * 隐藏)
SELECT xmin, xmax, cmin, cmax, ctid, * FROM mytable WHERE id = 42;

-- 典型的存活行(刚插入,尚未更新/删除)
xmin | xmax | cmin | cmax | ctid
-----+------+------+------+---------
 742 |    0 |    0 |    0 | (123,7)

-- 执行 UPDATE 后的行(旧版本,xmax 被更新事务设置)
xmin | xmax | cmin | cmax | ctid
-----+------+------+------+---------
 742 |  745 |    0 |    1 | (123,7)   ← 旧版本,xmax = 745

-- UPDATE 创建的新版本
xmin | xmax | cmin | cmax | ctid
-----+------+------+------+---------
 745 |    0 |    1 |    0 | (124,3)   ← 新版本,ctid 通常不同

重要行为

  • UPDATE → 创建新的行版本(新的 xmin,ctid 通常改变);旧版本被设置 xmax → 更新者提交后变为死行。

  • HOT UPDATE(堆内元组) → 更新发生在同一页面,索引不变 → 旧的 ctid 更新为指向新位置 → 避免索引膨胀。

  • DELETE → 设置 xmax,不会创建新版本。

  • VACUUM → 清理死行版本(即 xmax 已提交且小于最老运行事务的行)。

  • ctid 不稳定 ------ 切勿将其用作永久标识符(请用主键)。可用于调试重复行、追踪 HOT 链或底层页面检查。

底层访问(pageinspect 扩展)

复制代码
CREATE EXTENSION pageinspect;

-- 查看原始元组头字段 (t_xmin ≈ xmin, 等)
SELECT lp, t_xmin AS xmin, t_xmax AS xmax, t_cid AS cid, t_ctid AS ctid
FROM heap_page_items(get_raw_page('mytable', 0));

总结

  • xmin / xmax → 行的诞生与消亡(MVCC 的核心机制)

  • cmin / cmax → 多语句事务内部命令的先后顺序(除深度调试外很少需要)

  • ctid → 物理位置(经常变化,对内部机制分析和取证有用)

正是这些字段,使得 PostgreSQL 能够在 不加读锁 的情况下提供出色的并发能力 ------ 每个事务都能看到自己的一致数据版本。

相关推荐
共享家952718 分钟前
408 操作系统第一章
服务器·数据库·windows
这个DBA有点耶1 小时前
连拿六年第一后宣布出海:国产数据库凭什么敢撕掉“平替”的标签?
数据库·人工智能·架构
云和恩墨1 小时前
数据库监控简史:从会回答到能交付——AI-DBA如何成为真正的数字同事
数据库·人工智能·dba
Allen_LVyingbo2 小时前
NVIDIA CUDA Tile 在医疗计算中的算子形式化、算法重构与内核实现
大数据·python·算法·重构·知识图谱·健康医疗·数据库架构
这个DBA有点耶2 小时前
为什么删掉索引后,查询瞬间变快了?探讨MySQL的随机I/O与顺序I/O博弈
数据库·mysql·代码规范
全栈陈序员3 小时前
【Git】从入门到精通(一)—— Git简介:什么是版本控制系统
大数据·git·elasticsearch
中国搜索直付通3 小时前
分账系统有风险吗?资金安全怎么保障?
大数据·支付通道·分账系统·分账支付
kingx33 小时前
BugKu 渗透测试 4 实战:文件上传打点,5 Flag 全通
数据库·渗透测试·web·内网渗透
我命由我123453 小时前
Python 实用操作 - 文件操作(打开与关闭文件、读取文件、文件写入)
java·开发语言·前端·javascript·数据库·python·java-ee
一枕槐安4873 小时前
微调 vs Prompt:业务场景下两种方案成本 & 效果对比
大数据·人工智能·prompt·混合架构·推理成本·行为固化·知识边界