PostgreSQL 连接与锁问题排查(pg_stat_activity / 死锁 / 连接池)
2026-08-11 01:32:30 # 数据库

PG 的连接与锁问题,是运维高发的另一类故障。掌握 pg_stat_activitypg_locks,大部分都能快速定位。

一、连接数打满

1
2
3
SHOW max_connections;
SELECT count(*) FROM pg_stat_activity; -- 当前连接数
SELECT state, count(*) FROM pg_stat_activity GROUP BY state; -- 按状态分布

PG 还有 superuser_reserved_connections,会为超级用户预留连接,避免完全无法登录。

二、终止会话

1
2
3
SELECT pid, query, state FROM pg_stat_activity WHERE state <> 'idle';
SELECT pg_cancel_backend(pid); -- 取消该会话当前查询(事务回滚)
SELECT pg_terminate_backend(pid); -- 直接断开连接(更狠)

杀不掉时可能是系统进程或正在提交,需谨慎。

三、锁等待排查

PG 的锁信息在 pg_locks,但更直观的是直接查“谁阻塞了谁”:

1
2
3
4
5
6
7
SELECT blocked.pid AS blocked_pid,
blocking.pid AS blocking_pid,
blocked.query AS blocked_sql
FROM pg_stat_activity blocked
JOIN pg_locks bl ON bl.pid = blocked.pid AND NOT bl.granted
JOIN pg_locks kg ON kg.locktype = bl.locktype AND kg.objid = bl.objid
JOIN pg_stat_activity blocking ON kg.pid = blocking.pid AND kg.granted;

四、死锁

PG 会自动检测死锁并回滚其中一个事务,在日志中留下 DEADLOCK DETECTED。应用侧应捕获死锁异常并重试,而非 panic。

五、连接池

大量短连接会拖垮 PG。生产建议前置 PgBouncer

  • transaction 模式:连接复用最激进,适合高并发短事务;
  • 注意 transaction 模式下不能跨事务用临时表/会话级设置。

小结

连接看 pg_stat_activity + 用 pg_terminate_backend 救人;锁等待用上面的 join 查“阻塞链”;死锁 PG 自己回滚,应用做好重试即可。