PostgreSQL 19: 获取锁统计信息的 pg_stat_lock 视图

John Doe 三月 30, 2026

PostgreSQL 长期以来缺少锁统计信息的收集能力,难以定位和优化业务层级的锁冲突相关的开销。

image

特性提交日志

在 pgstats 中新增锁统计信息支持。

本次提交新增了一种名为PGSTAT_KIND_LOCK的全新统计类型,实现了对锁标签(lock tags)的统计功能,统计维度与pg_locks视图保持一致。由于统计数据会根据LockTagType中的锁标签数量进行上限限制,因此该实现采用固定大小的存储结构。

该新增统计类型会记录以下字段,用于深入分析数据库锁行为,同时避免对性能关键代码路径(如快速路径锁获取)造成影响:

  • waits(等待次数)和 wait_time(总等待时间):分别统计获取锁时需要等待的次数,以及等待获取锁的总耗时。这两项指标仅在锁成功获取后、且等待时间超过 deadlock_timeout 配置值时才会进行采集。
  • fastpath_exceeded(快速路径超限次数):统计因 max_locks_per_transaction 配额限制,导致无法通过快速路径(fast path) 获取锁的总次数。

新增的pg_stat_lock视图可用于查询锁统计数据,配套提供了对应的 SQL 函数pg_stat_get_lock()

讨论:https://postgr.es/m/aIyNxBWFCybgBZBS%40ip-10-97-1-34.eu-west-3.compute.internal

特性示例

新增系统视图pg_stat_lock包含三个关键指标如下:

指标名 类型 指标说明
waits bigint 锁等待累计次数,仅当锁等待时间超过deadlock_timeout、且最终成功获取锁时才会累加,避免短等待的高频统计影响性能
wait_time bigint 锁累计等待总时长,单位为毫秒,统计触发条件与waits一致,可精准量化锁等待对事务延迟的影响
fastpath_exceeded bigint max_locks_per_transaction槽位限制,无法通过快速路径获取锁的累计次数,直接反映锁优化机制的失效情况

通过查询pg_stat_lock视图,可直接定位导致性能问题的锁类型,快速区分是行锁冲突、表锁冲突、事务 ID 锁冲突还是其他锁类型导致的问题,无需复现卡顿现场。

查看累计等待总时长最长的TOP5锁类型,定位核心瓶颈:

SELECT
  locktype,
  waits AS total_wait_times,
  wait_time AS total_wait_ms,
  round(wait_time::numeric / waits, 2) AS avg_wait_ms,
  stats_reset
FROM pg_stat_lock
WHERE waits > 0
ORDER BY wait_time DESC
LIMIT 5;

查看事务 ID 锁与行锁的统计,判断是否存在长事务阻塞:

SELECT
  locktype,
  waits,
  wait_time AS total_wait_ms,
  round(wait_time::numeric / 1000 / 60, 2) AS total_wait_minutes
FROM pg_stat_lock
WHERE locktype IN ('transactionid', 'tuple');

transactionid锁等待占比极高:说明存在长事务未提交,阻塞了其他事务的提交,优化方向为拆分长事务、避免空闲事务。

tuple行锁等待占比极高:说明存在热点行并发更新冲突,优化方向为优化事务粒度、拆分热点数据。

relation表锁等待占比极高:说明存在 DDL 与 DML 冲突、或全表扫描加锁,优化方向为调整 DDL 执行窗口、优化查询索引。

另外,PostgreSQL 的快速路径锁是针对轻量级表锁的关键优化,可将锁获取性能提升一个数量级,但该机制的生效上限由max_locks_per_transaction控制。此前 DBA 无法判断该参数是否配置合理,只能被动应对性能问题。

通过fastpath_exceeded指标,可直接量化快速路径锁的超限次数,精准判断是否需要调大max_locks_per_transaction参数,释放数据库的锁处理性能。

查看快速路径锁超限的锁类型与累计次数:

SELECT
  locktype,
  fastpath_exceeded
FROM pg_stat_lock
WHERE fastpath_exceeded > 0
ORDER BY fastpath_exceeded DESC;

若查询结果中relation锁的fastpath_exceeded数值持续增长,说明当前max_locks_per_transaction配置过小,导致快速路径锁频繁失效。

可在postgresql.conf中调大该参数(默认 64),建议按 2 倍梯度上调,重启数据库后生效,再次观察fastpath_exceeded是否停止增长。

该参数上调会增加每个事务的内存开销,建议最大不超过 1024,避免内存过度占用。

非常不错的体验,感谢所有参与的社区人员。

参考

提交日志:https://git.postgresql.org/pg/commitdiff/4019f725f5d43f37b23222d06d20e3da1038d373