PG 19 引入了 pg_stat_lock 视图, 用于统计锁等待增量信息, 其中有一项 fastpath_exceeded 指标, 这个指标,值得单独讲一下,因为它不是“锁冲突次数”,而是“锁获取路径退化次数”。
先说结论: 它升高,不等于一定发生了锁等待;但它往往意味着你的锁管理成本在变贵。
什么是 fast-path lock
PostgreSQL 为一部分常见、低冲突的锁设计了 fast-path 快速路径。 核心目标只有一个:别什么锁都进主锁表。
因为主锁表是共享结构,访问它要付出更高的并发协调成本。 如果某些锁本来就很常见、冲突概率又低,那就没必要每次都走“重路径”。
所以 fast-path 本质上是一种优化机制: 能在 backend 自身的 fast-path 槽位里解决,就尽量别进全局主锁表。
fastpath_exceeded 统计的到底是什么
它统计的是:
某类锁本来尝试走 fast-path,但因为 fast-path 槽位容量不够,没走成,只能退回普通路径的次数。
注意两个边界:
它只说明一件事: 快速路径装不下了。
所以这个指标更像“锁子系统的容量压力信号”,而不是“阻塞事故计数器”。
为什么会 exceed
最典型的原因,就是单个事务或单条语句需要同时接触很多对象,导致 fast-path 槽位被打满。
这也是为什么官方测试特意用了“分区表”场景:
max_locks_per_transaction 的大量分区pg_stat_lock 里 relation 的 fastpath_exceeded 上升这背后的原理很直接:
所以它暴露的不是“你被谁堵住了”,而是:
你的 workload 正在把轻量锁路径挤爆。
为什么 DBA 和架构师要重视它
因为 fastpath_exceeded 高,通常意味着这几类风险之一正在发生:
这类问题的可怕之处在于: 它不一定马上表现成明显阻塞,但会先表现成锁管理开销上升、并发效率下降、抖动加剧。
也就是说,fastpath_exceeded 更像“事故前兆”,不是“事故现场”。
什么时候它最有解释力
这几个场景里,它特别有价值:
如果你发现:
waits 没有特别夸张relation.fastpath_exceeded 持续增长那就要警惕了。 问题可能不是“锁冲突严重”,而是“锁路径退化严重”。
它不说明什么
也要防止误判。
fastpath_exceeded 升高,不自动推出以下结论:
max_locks_per_transaction 就万事大吉因为如果根因是分区设计过碎、事务范围过宽、访问模式过散,那么调参数只是延后症状,不是消灭原因。
正确的排查思路
看到它升高后,建议按这个顺序想:
relation。max_locks_per_transaction
但这一步是容量兜底,不是默认答案。一句话概括
fastpath_exceeded 不是“锁冲突计数器”,而是锁获取从便宜路径退化到昂贵路径的压力指标。
它最适合回答的问题不是“谁阻塞了谁”,而是:
我的并发访问模式,是不是已经把 PostgreSQL 的轻量锁优化打穿了?
下面继续展开讲讲
fast-path lock 在 PostgreSQL 内部到底是怎么工作的fastpath_exceeded 高了以后,DBA 该怎么调参数、改表设计、改 SQL 访问路径1. fast-path lock 在 PostgreSQL 内部怎么工作
简单说: 它是 PostgreSQL 给一部分常见 relation 锁准备的“快捷通道”。
正常情况下,锁要进全局主锁表;但主锁表是共享结构,并发高时更贵。 所以 PostgreSQL 做了优化:
所以它的本质是:
fast-path = 便宜路径fastpath_exceeded 变高,表示:
它不直接等于锁冲突,但通常意味着锁管理成本上升。
2. fastpath_exceeded 高了以后,DBA 怎么做
先记住原则: 先找“为什么一个事务要碰这么多对象”,再考虑调参数。
优先排查这几类问题:
3. 参数怎么调
最直接的是看 max_locks_per_transaction。
它可以考虑调大,但要谨慎:
所以建议是:
4. 表设计怎么改
重点是减少单次操作接触的对象数。
常见做法:
一句话: 对象越多,锁越多,fast-path 越容易被打穿。
5. SQL 访问路径怎么改
核心目标也是一个: 让单条 SQL 少碰对象。
可以优先做这些:
6. 实战判断标准
如果你看到:
pg_stat_lock.fastpath_exceeded 持续升高relation那优先顺序应该是:
max_locks_per_transaction一句话总结
fast-path lock = PostgreSQL 为常见 relation 锁准备的低成本快捷通道fastpath_exceeded 高 = 快捷通道容量不够,越来越多锁回退到重路径max_locks_per_transaction