You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PostgreSQL表中未删除行的xmax系统列为何不为零?

为何PostgreSQL表中未删除行的xmax系统列不为零?

其实呀,PostgreSQL的xmax系统列可不是只用来标记行被删除的事务ID,它还有个重要职责:记录锁定该行的事务ID。所以即使行没被删除,只要满足某些场景,xmax就会是非零值,下面给你拆解几个常见情况:

  • 行级锁被持有:如果有事务通过SELECT ... FOR UPDATE、SELECT ... FOR SHARE这类语句锁定了某行,持有锁的事务ID就会被写入该行的xmax。比如你打开一个事务执行:

    BEGIN;
    SELECT * FROM product WHERE id=1 FOR UPDATE;
    

    这时候在另一个会话查询product表的xmax,就能看到对应行的xmax是这个未提交事务的ID,直到该事务提交或回滚、锁释放后,xmax才会恢复为0。

  • 未提交的删除/更新事务:如果有个事务执行了删除或更新该行的操作,但还没提交,在当前事务的快照里这行依然可见,但xmax已经被设置为那个操作事务的ID了。只有当该事务提交后,新的快照才会看不到这行;如果事务回滚,xmax会被标记为无效,后续查询里行还是正常可见的。

  • 外键约束的隐性锁:你的product表被stock表的外键引用,当对stock表做插入、更新product_id这类操作时,PostgreSQL会自动对product表的对应行加共享锁,防止在检查外键有效性期间该行被删除,这时候xmax也会记录下加锁的事务ID。比如插入一条stock记录时,数据库要确保对应的product存在,就会临时锁住那行,锁释放后xmax才会归零。

简单来说,xmax的作用是标记行的“删除者”或“锁定者”,不是只有删除才会让它非零。你可以先检查下有没有未提交的事务,或者近期有没有执行过行锁相关的操作,大概率能找到原因~

内容的提问来源于stack exchange,提问作者Mangu Singh Rajpurohit

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 08:27:06