pg_locks视图返回当前正在持有或等待的锁状态快照,每行表示一个backend进程与锁对象(表、行、事务ID等)的关联关系;需联查pg_stat_activity才能获取进程和SQL信息。

pg_locks 视图返回的是什么数据
pg_locks 是 PostgreSQL 内置的系统视图,它不存储锁的历史记录,只反映当前**正在持有或等待中**的锁状态。每一行代表一个锁对象(如表、行、事务ID等)与一个进程(pid)之间的关联关系。注意:它不是“谁锁了谁”的直观映射,而是“某个 backend 持有/等待某类锁”的快照。
如何查出带进程和 SQL 的完整锁信息
单独查 pg_locks 几乎没用,必须关联 pg_stat_activity 才能知道哪个会话在执行什么 SQL。常用组合查询如下:
SELECT l.pid, a.usename, a.application_name, a.client_addr, l.mode, l.granted, l.locktype, l.relation::regclass AS table_name, l.page, l.tuple, a.state, a.query FROM pg_locks l JOIN pg_stat_activity a ON l.pid = a.pid WHERE a.pid <> pg_backend_pid();
关键点:
-
l.granted = false表示该进程正在等待锁(可能被阻塞) -
l.locktype = 'relation'对应表级锁,'tuple'对应行级锁(需结合page和tuple定位) -
a.state = 'active'或'idle in transaction'的会话更值得关注 - 过滤掉
pg_backend_pid()是为了避免查到当前查询自身的锁(除非你故意要查)
为什么看不到行锁的具体 WHERE 条件
pg_locks 不保存 SQL 的谓词条件,它只记录锁作用的对象(比如第 5 页第 12 行),无法反推出 “WHERE id = 100” 这样的逻辑。如果你看到 locktype = 'tuple',只能确认有行锁存在,但具体锁了哪几行,得结合 query 字段里的 SQL + 表结构 + 当前事务的隔离级别来推理。
常见误区:
- 认为
turtle字段是行号 —— 实际是堆页面内的元组偏移,不是主键值 - 试图用
pg_locks查死锁源头 —— 它本身不体现等待链,需配合pg_blocking_pids()或pg_stat_activity.blocked_by(v13+) - 忽略事务未提交导致的长持锁 ——
state = 'idle in transaction'的会话常是隐形锁源
性能与权限注意事项
pg_locks 查询开销极小,但默认只对超级用户或拥有 pg_read_all_data(v14+)角色可见。普通用户即使被授权访问该视图,也只能看到自己 backend 的锁(pg_stat_activity 同理)。若需监控他人锁状态,必须由 DBA 显式授权:
GRANT pg_read_all_data TO monitor_user;
另外,pg_locks 中的 pid 是 backend 进程 ID,不是操作系统 PID;重启 PostgreSQL 后所有锁清空,该视图也随之重置。
真正难的不是查锁,而是判断哪个锁不该长期存在、哪个 idle in transaction 其实卡在应用层没 commit —— 这些得靠 query 内容和业务上下文交叉验证。










