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

PostgreSQL非关联表间死锁问题排查及技术疑问

2022-10-12 20:23:27 KST [40P01] [11983 (4)] ... ERROR:  deadlock detected
2022-10-12 20:23:27 KST [40P01] [11983 (5)] ... DETAIL:  Process 11983 waits for ShareLock on transaction 12179793; blocked by process
11893.
    Process 11893 waits for ShareLock on transaction 12179803; blocked by process 12027.
    Process 12027 waits for ExclusiveLock on tuple (1881,5) of relation 17109 of database 16384; blocked by process 11983.
    Process 11983: update B set ... where id=$1
    Process 11893: update A set ... where a=$1 and b=$2
    Process 12027: update B set ... where id=$1
2022-10-12 20:23:27 KST [40P01] [11983 (6)] ... HINT:  See server log for query details.
2022-10-12 20:23:27 KST [40P01] [11983 (7)] ... CONTEXT:  while locking tuple (1881,5) in relation "B"
2022-10-12 20:23:27 KST [40P01] [11983 (8)] ... STATEMENT:  update B set ... where id=$1
PostgreSQL死锁疑问解答

1. 进程11983为何等待进程11893?

根据日志DETAIL部分,进程11983在等待事务12179793上的ShareLock,而这个锁被进程11893持有。这里的ShareLock属于事务ID锁,用于避免并发事务间的可见性冲突(比如快照过旧、事务ID回卷问题)。

进程11893执行表A的更新时,会持有自身事务ID(12179793)的ShareLock;进程11983执行表B的更新时,需要获取该事务ID的ShareLock来确认事务状态,因此被进程11893阻塞。

2. 进程12027执行update语句时是否会使用ShareLock?

Update语句核心操作会对目标元组加ExclusiveLock(排他锁),但会间接涉及ShareLock:

  • PostgreSQL在验证事务ID有效性时,会持有自身事务ID的ShareLock,这也是进程11893等待进程12027的原因。
  • 若update的where子句扫描阶段需要确认其他事务状态,也可能临时申请事务ID的ShareLock,但元组修改本身不会用ShareLock。

所以进程12027执行update时,不会主动申请元组的ShareLock,但会持有自身事务ID的ShareLock。

3. 如何查询tuple(1881,5)对应的实际数据?

按以下步骤操作:

步骤1:确认元组所属表(可选,已明确是表B)

日志中relation 17109是表的OID,执行语句验证表名:

SELECT relname FROM pg_class WHERE oid = 17109;

步骤2:查询元组数据

PostgreSQL用ctid标识元组,格式为(块号, 元组序号),直接查询表B中对应ctid的数据:

SELECT * FROM "B" WHERE ctid = '(1881,5)';

注意:如果元组已被删除或清理,可能需要通过表的备份或历史快照查询,未清理前ctid有效。

内容的提问来源于stack exchange,提问作者DongHoon Kim

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 05:40:23