一、支持版本
| PostgreSQL 版本 | 最早支持版本 | 插件版本 |
| PostgreSQL 18 | v18.6_r1.15 | pgsentinel 1.4.1 |
注意:说明:
注意:这篇适用于云数据库 PostgreSQL 18集成版本。
二、插件简介
pg_stat_activity 只能看当前时刻。很多线上问题持续时间很短,等 DBA 登录时,现场已经没有了。
pgsentinel 解决的是这类问题。它可以记录:
·采样时间;
·会话 PID、用户、数据库、应用名;
·会话状态和等待事件;
·当前 SQL 和顶层 SQL;
·阻塞者数量、阻塞者 PID、阻塞者状态;
·长事务、空闲事务相关信息。
典型用途:
·回看某个时间点哪些会话在运行;
·排查锁等待和阻塞链;
·抓取偶发慢 SQL 的真实参数;
·分析存储过程内部实际执行的 SQL;
·给 pg_profile 提供 ASH 数据。
三、配置预加载
pgsentinel 需要共享内存和后台进程,必须预加载。建议同时加载 pg_stat_statements。
shared_preload_libraries = 'pg_stat_statements,pgsentinel'track_activity_query_size = 2048pg_stat_statements.track = allpgsentinel.db_name = 'postgres'pgsentinel_ash.sampling_period = 1pgsentinel_ash.max_entries = 1000pgsentinel_ash.track_idle_trans = offpgsentinel_pgssh.enable = offpgsentinel_pgssh.max_entries = 10000
注意:说明:
注意:pgsentinel.db_name 必须是已经存在的数据库。后台进程会连接这个库。
修改后重启数据库:
pg_ctl -D $PGDATA restart
四、创建扩展
pgsentinel 需要管理员创建:
CREATE EXTENSION pg_stat_statements;CREATE EXTENSION pgsentinel;
可以指定 schema:
CREATE SCHEMA ash;CREATE EXTENSION pgsentinel SCHEMA ash;
五、授权
GRANT pg_monitor TO monitor_user;
普通用户没有 pg_monitor 时,只能看到自己的会话历史。
六、检查后台进程
SELECT pid, backend_type, application_name, datnameFROM pg_stat_activityWHERE backend_type = 'pgsentinel' OR application_name = 'pgsentinel';
如果没有结果,先检查 shared_preload_libraries 和 pgsentinel.db_name。
七、回看最近活动会话
SELECT ash_time, pid, usename, datname, application_name, state, 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 DESC, pidLIMIT 50;
wait_event_type 为空时表示当时没有等待事件。
八、查看等待分布
SELECT coalesce(wait_event_type, 'ON CPU') AS wait_type, coalesce(wait_event, 'ON CPU') AS wait_event, count(*) AS samplesFROM pg_active_session_historyWHERE ash_time > now() – interval '30 minutes'GROUP BY 1, 2ORDER BY samples DESCLIMIT 15;
因为采样周期固定,samples 可以近似理解为活跃秒数。
九、查看阻塞链
SELECT ash_time, pid AS blocked_pid, usename AS blocked_user, wait_event_type, wait_event, blockers, blockerpid, blocker_state, substring(query, 1, 80) AS blocked_queryFROM pg_active_session_historyWHERE blockers > 0 AND ash_time > now() – interval '1 hour'ORDER BY ash_time DESCLIMIT 30;
查看阻塞次数最多的进程:
SELECT blockerpid, blocker_state, count(*) AS times_blocking, count(DISTINCT pid) AS victimsFROM pg_active_session_historyWHERE blockers > 0GROUP BY 1, 2ORDER BY times_blocking DESCLIMIT 10;
十、查看活跃时间最多的 SQL
SELECT queryid, cmdtype, count(*) AS active_samples, count(DISTINCT pid) AS sessions, substring(min(query), 1, 80) AS sample_queryFROM pg_active_session_historyWHERE ash_time > now() – interval '30 minutes' AND queryid IS NOT NULL AND queryid <> 0GROUP BY queryid, cmdtypeORDER BY active_samples DESCLIMIT 15;
十一、查看存储过程内部 SQL
SELECT substring(top_level_query, 1, 80) AS top_sql, substring(query, 1, 80) AS inner_sql, cmdtype, count(*) AS samplesFROM pg_active_session_historyWHERE top_level_query IS DISTINCT FROM query AND ash_time > now() – interval '30 minutes'GROUP BY 1, 2, 3ORDER BY samples DESCLIMIT 20;
十二、查看 SQL 统计历史
需要先开启:
pgsentinel_pgssh.enable = on
该参数需要重启。
查询:
SELECT ash_time, queryid, calls, total_exec_time, rows, wal_bytesFROM pg_stat_statements_historyORDER BY ash_time DESCLIMIT 20;
注意:说明:
注意:pg_stat_statements_history 保存的是 pg_stat_statements 的核心字段快照,不是完整字段快照。
十三、函数和视图
| 对象 | 说明 |
| pg_active_session_history() | 返回 ASH 环形缓冲区中的记录 |
| pg_active_session_history | ASH 视图 |
| pg_stat_statements_history() | 返回 SQL 统计历史 |
| pg_stat_statements_history | SQL 统计历史视图 |
| get_parsedinfo(int) | 查看指定 PID 当前解析出的语句,传 -1 表示所有进程 |
十四、参数说明
| 参数 | 默认值 | 生效方式 | 说明 |
| pgsentinel.db_name | postgres | 重启 | 后台进程连接的数据库 |
| pgsentinel_ash.sampling_period | 1 | reload | ASH 采样周期,单位秒 |
| pgsentinel_ash.max_entries | 1000 | 重启 | ASH 环形缓冲区条数 |
| pgsentinel_ash.track_idle_trans | off | reload | 是否记录 idle in transaction |
| pgsentinel_pgssh.enable | off | 重启 | 是否采集 SQL 统计历史 |
| pgsentinel_pgssh.max_entries | 10000 | 重启 | SQL 统计历史缓冲条数 |
track_activity_query_size 会影响 SQL 文本长度,也会影响共享内存占用。调大前要估算内存。
十五、常见问题
Q1:创建扩展为什么报权限错误?
A:pgsentinel 需要管理员创建。
Q2:视图为什么一直为空?
A:先确认后台进程存在,再确认有活跃会话。空闲数据库没有 ASH 记录是正常的。还要检查 pgsentinel.db_name 指向的数据库是否存在。
Q3:为什么只能回看很短时间?
A:ASH 存在环形缓冲区中。可回看时长约等于 max_entries / 平均活跃会话数。可以增大 pgsentinel_ash.max_entries,但会占用更多共享内存并需要重启。
Q4:数据库重启后历史为什么没了?
A:这是预期行为。ASH 在共享内存中。需要长期保留时,用 pg_profile 定期采样落盘。
Q5:看不到 idle in transaction 怎么办?
A:需要开启参数 pgsentinel_ash.track_idle_trans,设置该参数的值为 on,设置后 reload 配置即可开始记录这类会话,之后就可以看到 idle in transaction 了。
Q6:普通用户为什么看不到别人的 SQL?
A:这是权限隔离。需要全量视角时授予 pg_monitor。
十六、卸载
DROP EXTENSION pgsentinel;
然后从 shared_preload_libraries 中移除 pgsentinel 并重启数据库。卸载或重启后,共享内存中的 ASH 和 SQL 统计历史会丢失。
十七、相关参考
·PostgreSQL 可观测性插件套件使用手册
·pg_profile 插件使用手册