本文介绍云数据库 PostgreSQL 18中的可观测性插件套件。套件包含
pg_stat_kcache、pg_wait_sampling、pgsentinel、pg_profile,配合 PostgreSQL 自带的 pg_stat_statements 使用。本文按实际使用顺序说明安装、配置和常见排查方法。
支持版本
PostgreSQL 版本 | 最早支持版本 | 插件版本 |
PostgreSQL 18 | v18.6_r1.15 | pg_stat_kcache 2.3.1、pg_wait_sampling 1.1、pgsentinel 1.4.1、pg_profile 4.10 |
说明:
本文以云数据库 PostgreSQL 18集成版本为准。社区同名插件的功能和权限策略可能不同。
插件简介
这套插件分别解决不同问题:
插件 | 主要用途 | 常用场景 |
pg_stat_kcache | 统计 SQL 的 CPU、物理读写、缺页、上下文切换 | 判断一条 SQL 是耗 CPU 还是耗 IO |
pg_wait_sampling | 采样等待事件,提供当前等待、历史等待和等待画像 | 判断数据库慢在锁、IO、LWLock 还是 CPU |
pgsentinel | 保存活动会话历史,提供 ASH 能力 | 事后回看某个时间点谁在执行、谁被阻塞 |
pg_profile | 周期性快照和 HTML 报告 | 生成某个时间段的性能报告、做上线前后对比 |
pg_profile 是报告和历史仓库。前三个插件提供数据,pg_profile 负责采集、保存和生成报告。环境准备
修改配置
pg_stat_kcache、pg_wait_sampling、pgsentinel 需要预加载。pg_profile 不需要预加载。在
postgresql.conf 中配置:shared_preload_libraries = 'pg_stat_statements,pg_stat_kcache,pg_wait_sampling,pgsentinel'pg_stat_statements.track = allpg_stat_statements.max = 10000pgsentinel.db_name = 'postgres'
说明:
pg_stat_statements 必须放在前面,后面的插件需要使用 queryid。修改后重启数据库:
pg_ctl -D $PGDATA restart
创建扩展
在需要观测的数据库中执行:
CREATE EXTENSION pg_stat_statements;CREATE EXTENSION pg_stat_kcache;CREATE EXTENSION pg_wait_sampling;CREATE EXTENSION pgsentinel;CREATE EXTENSION dblink;CREATE SCHEMA profile;CREATE EXTENSION pg_profile SCHEMA profile;
说明:
pgsentinel 和 dblink 通常需要管理员创建。pg_profile 依赖 dblink。pg_profile 建议安装在单独 schema 中,例如 profile。检查安装结果
SELECT extname, extversionFROM pg_extensionWHERE extname IN ('pg_stat_statements','pg_stat_kcache','pg_wait_sampling','pgsentinel','dblink','pg_profile')ORDER BY extname;
快速使用
1. 看数据库主要在等什么
SELECT coalesce(event_type, 'ON CPU') AS event_type,coalesce(event, 'ON CPU') AS event,sum(count) AS samplesFROM pg_wait_sampling_profileGROUP BY 1, 2ORDER BY samples DESCLIMIT 10;
如果
ON CPU 多,说明主要在用 CPU;如果 Lock 多,先看锁等待;如果 IO 多,继续看真实读写。2. 看哪些 SQL 消耗 CPU 或物理 IO
SELECT substring(query, 1, 80) AS query,round((exec_user_time + exec_system_time)::numeric, 3) AS cpu_sec,pg_size_pretty(exec_reads) AS phys_read,pg_size_pretty(exec_writes) AS phys_writeFROM pg_stat_kcache_detailWHERE top IS TRUEORDER BY exec_user_time + exec_system_time DESCLIMIT 10;
3. 回看最近活动会话
SELECT ash_time, pid, usename, application_name,coalesce(wait_event_type, 'ON CPU') AS wait_type,wait_event, substring(query, 1, 80) AS queryFROM pg_active_session_historyWHERE ash_time > now() - interval '10 minutes'ORDER BY ash_time DESCLIMIT 20;
4. 生成性能报告
至少采集两个 sample:
SELECT profile.take_sample();-- 等待一段时间或运行负载SELECT profile.take_sample();SELECT * FROM profile.show_samples();
生成报告:
\\o /tmp/pg_profile_report.htmlSELECT profile.get_report('local', 1, 2);\\o
将
1、2 换成实际 sample id。排查思路
数据库突然变慢
1. 先用
pg_wait_sampling_profile 看等待分布。2. 如果是 CPU 或 IO,再用
pg_stat_kcache_detail 找 SQL。3. 如果是锁等待,再用
pg_active_session_history 找阻塞者。4. 最后用
pg_profile 对故障时间段生成报告。上线前后对比
上线前采集两个 sample,上线后再采集两个 sample,然后生成差异报告:
SELECT profile.get_diffreport('local', 1, 2, 3, 4);
需要长期保留某个时间段
为 sample 区间创建 baseline:
SELECT profile.create_baseline('local', 'before_upgrade', 1, 2, 90);SELECT * FROM profile.show_baselines('local');
权限说明
操作 | 建议角色 |
查看全量监控数据 | pg_monitor 或 pg_read_all_stats |
执行采样 | pg_monitor |
修改 pg_profile server 配置 | pg_profile 扩展 owner 或管理员 |
reset 统计 | 管理员 |
普通用户通常只能看到自己的数据。reset 类操作会清空诊断现场,不能开放给普通监控账号。
常见问题
Q1:创建扩展时报 must be loaded via shared_preload_libraries 怎么办?
A:说明对应 C 插件没有预加载。把插件加入
shared_preload_libraries 后重启数据库。Q2:视图为空是不是插件没生效?
A:不一定。刚启动、刚 reset 或没有业务负载时都可能为空。也可能是当前用户没有全量权限,只能看到自己的数据。
Q3:pg_profile 报连接失败怎么办?
A:检查
profile.show_servers() 中的连接串。远端连接需要加入 profile.server_connstr_allowlist,连接串中不要写明文密码。Q4:报告很大怎么办?
A:生成 HTML 时使用
psql -qAt -o report.html,不要用默认表格输出。可适当降低 pg_profile.topn 或缩短保留时间。卸载
建议按依赖顺序卸载:
DROP EXTENSION pg_profile;DROP EXTENSION pg_stat_kcache;DROP EXTENSION pg_wait_sampling;DROP EXTENSION pgsentinel;DROP EXTENSION pg_stat_statements;DROP EXTENSION dblink;
然后从
shared_preload_libraries 中移除 C 插件并重启数据库。说明:
DROP EXTENSION pg_profile 会删除本地历史仓库。需要保留数据时,先使用 profile.export_data() 导出。