由 John Doe 四月 20, 2026
现代 PostgreSQL 中最有用的一个调优工具就是等待事件系统。

目录
介绍
当查询速度变慢或数据库陷入 CPU 瓶颈时,一个很自然的问题是:“会话实际在等待什么?” Postgres 通过视图中的pg_stat_activity两列公开了此信息:
SELECT pid, wait_event_type, wait_event, query
FROM pg_stat_activity
WHERE wait_event IS NOT NULL;
视图 pg_wait_events 提供了有关等待事件的描述,可以与 pg_stat_activity 结合使用,如下所示:
SELECT a.pid, a.wait_event, w.description
FROM pg_stat_activity a JOIN
pg_wait_events w ON (a.wait_event_type = w.type AND
a.wait_event = w.name)
WHERE a.wait_event IS NOT NULL and a.state = 'active';
下面我们来重点探讨一类等待事件:LWLock 等待。
为什么会出现 LWLock 等待?
LWLock 代表轻量级锁(Lightweight Lock)。这些是 PostgreSQL 内部的同步实现,用于协调对共享内存结构的访问。
在健康的系统中,LWLocks 的获取和释放都非常迅速。然而,在以下情况下,它们可能会变得可见:
- 资源竞争加剧
- 多个会话访问相同的内部结构,如:共享缓冲区、WAL 缓冲区
- CPU 饱和现象发生
- 共享内存结构成为热点
OLTP 工作负载会产生高并发性和对共享资源的频繁访问,因此您经常会看到锁等待和缓冲区或 IO 相关的等待。
在pg_stat_activity中看到 LWLock 等待并不一定意味着出了问题。但持续的 LWLock 争用通常表明工作负载的某个地方存在扩展性问题。
常见的 LWLock 等待事件
在现实世界的事件中,一些 LWLock 事件会频繁出现。
了解这些因素有助于缩小问题根源的范围。
LWLock - buffer_content
当 Postgres 进程争用共享缓冲区页面时,就会发生这种情况。
常见病因包括:
- 对同一行的多次并发更新
- 索引大幅修改
- 热表接收到大量写入
如果看到这些锁定图标,请尝试以下故障排除步骤:
- 检查是否存在写入密集型工作负载
- 检查频繁更新的表
- 查看是否缺失索引导致页面访问过多
LWLock - WALWriteLock
这表明在写入 WAL 预写日志时存在争用。
常见原因:
- 高写入吞吐量
- 大批量插入或更新
- 低速存储影响 WAL 刷写
可能的诊断步骤:
- 检查 WAL 生成速率
- 检查磁盘延迟
- 审查批量写入类工作负载
在某些系统中,这表现为提交延迟峰值。
LWLock 问题诊断
在调查 LWLock 等待问题时,通常有几个步骤会有所帮助。
寻找占主导地位的等待事件
首先确定出现频率最高的 LWLock 类型:
SELECT wait_event, count(*)
FROM pg_stat_activity
WHERE wait_event_type = 'LWLock'
GROUP BY wait_event
ORDER BY count(*) DESC;
检查工作负荷特征
需要提出的问题:
- 同时有多个写入者?
- 是否有单个表正在接收大量更新?
- 事务处理量是否极高?
检查连接数
大量的连接会加剧资源争用。连接池通常能显著降低 LWLock 的压力。
查看查询模式
频繁查询访问相同的行或页面会造成热点。
结语
PostgreSQL 等待事件系统提供了关于数据库内部运行情况的宝贵信息。特别是 LWLock,它能够揭示共享内存结构内部的争用情况,而这些争用在其他情况下是不可见的。在调查性能问题时,一个有效的经验法则是:如果多个会话都在等待同一个 LWLock,那么通常存在某个工作负载的热点。一旦确定了争用的位置,解决问题的路径就会变得清晰得多。
另外,在 Redrock Postgres 最新的版本中,我们添加了等待事件统计信息收集扩展rp_wait_states,方便进行性能问题的诊断分析。