postgres-deadlock

PostgreSQL 死锁的定位与处理

现象

日志出现 ERROR: deadlock detected,事务被中止,应用收到 deadlock_detected。数据库会选择一个事务回滚,通常不是数据库故障。

快速定位

SELECT * FROM pg_stat_activity WHERE state <> 'idle';
SELECT * FROM pg_locks WHERE NOT granted;
SELECT pid, wait_event_type, wait_event, query
FROM pg_stat_activity WHERE wait_event_type = 'Lock';
SHOW deadlock_timeout;
SHOW log_lock_waits;

日志:

grep -i deadlock /var/log/postgresql/postgresql-*.log | tail -20

常见根因

  1. 不同事务以相反顺序更新同一批行。
  2. 事务过长,持有锁期间等待外部调用。
  3. 缺索引导致更新/删除扫描过多行。
  4. 外键、唯一约束或批量更新引入额外锁。
  5. 应用重试没有退避,放大冲突。

修复

相关命令

读完自测

合上页面,先回答,再展开对照。

  1. 日志出现 deadlock detected 意味着什么?
  2. 如何定位当前锁等待和未授予的锁?
  3. 常见根因与修复方向是什么?
答案
  1. 数据库检测到事务间循环等待并选择一个事务回滚,通常是应用访问顺序问题,而不是数据库故障。
  2. 查 pg_stat_activity 中 wait_event_type = 'Lock' 的会话和 pg_locks 中 NOT granted 的记录,并开启 log_lock_waits 观察。
  3. 常见于反向加锁顺序、事务过长和缺索引;应统一加锁顺序、缩短事务、补索引,并对死锁做有限重试。