一、支持版本
| PostgreSQL 版本 | 最早支持版本 | 插件版本 |
| PostgreSQL 18 | v18.6_r1.15 | pg_wait_sampling 1.1 |
注意:说明:
注意:这篇适用于云数据库 PostgreSQL 18集成版本。
二、插件简介
pg_stat_activity 只能看到当前这一刻的 wait_event。如果问题已经过去,现场就没有了。
pg_wait_sampling 通过后台进程周期性采样等待事件,提供三类数据:
| 视图 | 用途 |
| pg_wait_sampling_current | 查看当前每个进程在等什么 |
| pg_wait_sampling_history | 查看最近一段时间的等待时间线 |
| pg_wait_sampling_profile | 查看累计等待画像 |
常见问题:
·数据库慢,是 CPU 忙还是在等锁、等 IO。
·某段时间内主要等待事件是什么。
·某条 SQL 是否经常等待锁或 IO。
四、配置预加载
pg_wait_sampling 需要共享内存和后台进程,必须预加载。建议同时加载 pg_stat_statements。
shared_preload_libraries = 'pg_stat_statements,pg_wait_sampling'pg_wait_sampling.history_size = 5000pg_wait_sampling.history_period = 10pg_wait_sampling.profile_period = 10pg_wait_sampling.profile_pid = onpg_wait_sampling.profile_queries = toppg_wait_sampling.profile_max_entries = 100000pg_wait_sampling.sample_cpu = on
修改后重启数据库:
pg_ctl -D $PGDATA restart
五、创建扩展
CREATE EXTENSION pg_stat_statements;CREATE EXTENSION pg_wait_sampling;
可以指定 schema:
CREATE SCHEMA pgws;CREATE EXTENSION pg_wait_sampling SCHEMA pgws;
六、授权
GRANT pg_monitor TO monitor_user;
普通用户没有 pg_monitor 时,只能看到自己的进程。
八、查看当前等待
SELECT c.pid, a.usename, a.state, coalesce(c.event_type, 'ON CPU') AS event_type, coalesce(c.event, 'ON CPU') AS event, substring(a.query, 1, 80) AS queryFROM pg_wait_sampling_current cLEFT JOIN pg_stat_activity a ON a.pid = c.pidORDER BY c.event_type NULLS LAST;
event_type 为空时表示进程没有等待事件,正在使用 CPU。
九、查看累计等待画像
SELECT coalesce(event_type, 'ON CPU') AS event_type, coalesce(event, 'ON CPU') AS event, sum(count) AS samples, round(100.0 * sum(count) / sum(sum(count)) OVER (), 2) AS pctFROM pg_wait_sampling_profileGROUP BY 1, 2ORDER BY samples DESCLIMIT 15;
常见判断:
| event_type | 说明 |
| ON CPU | 进程没有等待,主要在用 CPU |
| Lock | 锁等待 |
| IO | IO 等待 |
| LWLock | 内部轻量锁等待 |
| Client | 等客户端读写 |
| Timeout | 主动等待,例如 pg_sleep |
十、查看最近等待历史
SELECT ts, pid, coalesce(event_type, 'ON CPU') AS event_type, coalesce(event, 'ON CPU') AS event, queryidFROM pg_wait_sampling_historyWHERE ts > now() – interval '30 seconds'ORDER BY ts DESC, pidLIMIT 50;
history 是环形缓冲区,满了会覆盖旧数据。
十一、关联 SQL 文本
SELECT coalesce(p.event_type, 'ON CPU') AS event_type, coalesce(p.event, 'ON CPU') AS event, sum(p.count) AS samples, substring(s.query, 1, 80) AS queryFROM pg_wait_sampling_profile pLEFT JOIN pg_stat_statements s ON s.queryid = p.queryidWHERE p.queryid <> 0GROUP BY 1, 2, 4ORDER BY samples DESCLIMIT 15;
需要 pg_stat_statements 正常安装,并且 profile_queries 不为 none。
十二、建立一个观察窗口
SELECT pg_wait_sampling_reset_profile();– 等待或运行负载SELECT pg_sleep(60);SELECT coalesce(event_type, 'ON CPU'), coalesce(event, 'ON CPU'), sum(count)FROM pg_wait_sampling_profileGROUP BY 1, 2ORDER BY 3 DESC;
pg_wait_sampling_reset_profile() 只能由管理员执行。
十三、函数和视图
| 对象 | 说明 |
| pg_wait_sampling_get_current(pid int4) | 查看指定进程当前等待,传 NULL 返回全部 |
| pg_wait_sampling_get_history() | 返回等待历史环形缓冲区 |
| pg_wait_sampling_get_profile() | 返回累计等待画像 |
| pg_wait_sampling_reset_profile() | 清空等待画像,仅管理员可执行 |
| pg_wait_sampling_current | 当前等待视图 |
| pg_wait_sampling_history | 等待历史视图 |
| pg_wait_sampling_profile | 等待画像视图 |
十四、参数说明
| 参数 | 默认值 | 生效方式 | 说明 |
| pg_wait_sampling.history_size | 5000 | reload | history 环形缓冲区条数 |
| pg_wait_sampling.history_period | 10 | reload | history 采样周期,单位毫秒 |
| pg_wait_sampling.profile_period | 10 | reload | profile 采样周期,单位毫秒 |
| pg_wait_sampling.profile_pid | on | reload | profile 是否按 PID 区分 |
| pg_wait_sampling.profile_queries | top | reload | 是否记录 queryid,取值 none、top、all |
| pg_wait_sampling.profile_max_entries | 100000 | reload | profile 最大条目数 |
| pg_wait_sampling.sample_cpu | on | reload | 是否采样未等待进程 |
参数是 SIGHUP 级别,修改后执行:
SELECT pg_reload_conf();
十六、Q1:查询时提示“必须预加载”怎么办?
A:把 pg_wait_sampling 加入 shared_preload_libraries,然后重启数据库。
十七、Q2:queryid 怎么都是0?
A:检查 pg_wait_sampling.profile_queries 是否为 none;检查是否安装并预加载 pg_stat_statements;检查 pg_stat_statements 是否排在 pg_wait_sampling 前面。
十八、Q3:pid 怎么都是0?
A:说明 pg_wait_sampling.profile_pid = off,所有进程合并统计。需要按进程看时改成 on。
十九、Q4:history 为什么只能回溯很短时间?
A:history 是环形缓冲区。可回溯时间受 history_size、活跃进程数和采样周期影响。可以增大 history_size 或增大 history_period。长期保留建议使用 pg_profile。
20、Q5:普通用户只能看到自己的数据吗?
A:这是预期行为。需要全量数据时授予 pg_monitor。
21、Q6:reset 报权限错误是怎么回事?
A:reset 是破坏性操作,只允许管理员执行。
22、卸载
DROP EXTENSION pg_wait_sampling;
然后从 shared_preload_libraries 中移除 pg_wait_sampling 并重启数据库。
卸载或重启后,history 和 profile 中的内存数据都会丢失。
23、相关参考
·PostgreSQL 可观测性插件套件使用手册
·pg_profile 插件使用手册