Skip to content

常用监控 SQL 汇总 ​

前面几页逐个讲清了核心统计视图的字段与语义,本页做一件事:把日常运维真正会反复用到的监控 SQL 汇总成一份可执行的「工具手册」。每条查询都标注数据来源视图、适用场景与告警建议,可以直接复制进巡检脚本、监控系统自定义查询或应急排查手册。

组织方式按排障场景划分:连接数、长事务、锁等待、命中率、表膨胀、索引使用、WAL、归档、复制延迟、Top SQL。每节先给「一句话答案」式的查询,再给进阶变体。所有查询都是只读的,可以在生产库安全执行(个别建议加超时保护,见注意事项)。

本页是监控章节的收束与索引:每节末尾链接到对应的专题页或全站相关页面,需要深挖语义时跳过去读。

前置知识

建议先阅读:pg_stat_database 与 pg_stat_user_tables

基础概念 ​

监控 SQL 的三种数据源 ​

数据源特点代表视图适合回答
实时快照查一次看一次,无历史pg_stat_activity、pg_locks现在出什么事了
累计计数自启动/重置以来的总和pg_stat_database、pg_stat_user_tables、pg_stat_archiver、pg_stat_wal周期内的速率与趋势
聚合扩展带归一化与重置语义pg_stat_statements哪些 SQL 最重

三种数据源决定三种使用方式:实时快照直接查;累计计数必须两次采样求增量;聚合扩展既要看绝对值也要看 stats_reset 时间。

增量采样框架 ​

几乎所有累计型指标都套用同一个模式:

sql
-- 建快照表(一次性)
CREATE TABLE IF NOT EXISTS monitor_snapshots (
    metric     text,
    taken_at   timestamptz DEFAULT now(),
    value      numeric,
    extra      jsonb
);

-- 采样函数示例:每次调用记录当前累计值
INSERT INTO monitor_snapshots (metric, value, extra)
SELECT 'xact_commit_' || datname, xact_commit,
       jsonb_build_object('hit', blks_hit, 'read', blks_read)
FROM pg_stat_database
WHERE datname = current_database();

速率 =(当前值 − 上次值)/ 时间差。监控系统的 exporter 之所以能直接画速率图,内部做的正是这件事;自建脚本时也请遵循这个模式,不要对累计值设绝对阈值告警。

执行安全约定 ​

  • 监控账号使用只读权限 + pg_read_all_stats,不给写权限更不给超级用户。
  • 巡检会话设置 statement_timeout(如 30s),防止个别视图在极端负载下查询本身拖慢实例。
  • pg_locks、pg_stat_activity 这类实时视图在高并发实例上查询有成本,采样频率秒级起步即可,不要毫秒级轮询。

语法与用法 ​

本页所有查询按如下约定编写,可直接粘贴执行:

sql
-- 约定:所有查询默认在目标库上以只读方式执行
SET statement_timeout = '30s';
SET default_transaction_read_only = on;

各节查询的输出都设计为「一眼可判异常」的形态:关键指标在前、可读性换算(pg_size_pretty、百分比)在后、异常候选排前面。

详细说明 ​

连接数与会话状态 ​

数据源:pg_stat_activity(实时)。

sql
-- 连接总览:按数据库、用户、应用、状态分组
SELECT datname,
       usename,
       application_name,
       state,
       count(*) AS conns
FROM pg_stat_activity
WHERE backend_type = 'client backend'
GROUP BY datname, usename, application_name, state
ORDER BY conns DESC;

-- 连接使用率(对照 max_connections)
SELECT count(*) AS current_conns,
       current_setting('max_connections')::int AS max_conns,
       round(100.0 * count(*) / current_setting('max_connections')::int, 1) AS usage_pct
FROM pg_stat_activity
WHERE backend_type = 'client backend';

告警建议:使用率 > 80% 触发容量告警;idle in transaction 出现即告警。治理手段见《PgBouncer 连接池》与《连接池配置(PgBouncer)》两页。

长事务与空闲事务 ​

数据源:pg_stat_activity(实时)。

sql
-- 运行超过 5 分钟的事务(含空闲事务)
SELECT pid,
       datname,
       usename,
       state,
       now() - xact_start AS xact_age,
       now() - query_start AS query_age,
       backend_xid,
       backend_xmin,
       left(query, 80) AS last_query
FROM pg_stat_activity
WHERE xact_start IS NOT NULL
  AND now() - xact_start > interval '5 minutes'
ORDER BY xact_start;

长事务的连带伤害(锁等待、表膨胀、复制延迟)在 pg_stat_activity 页已详细展开;本查询建议 1 分钟采样一次,最老事务年龄超过阈值即告警。

锁等待与阻塞链 ​

数据源:pg_stat_activity + pg_locks + pg_blocking_pids()。

sql
-- 当前所有锁等待及其阻塞者
SELECT w.pid AS waiting_pid,
       w.usename AS waiting_user,
       now() - w.query_start AS waiting_for,
       left(w.query, 60) AS waiting_query,
       b.pid AS blocking_pid,
       b.state AS blocking_state,
       left(b.query, 60) AS blocking_query
FROM pg_stat_activity w
JOIN pg_stat_activity b
  ON b.pid = ANY (pg_blocking_pids(w.pid))
WHERE w.wait_event_type = 'Lock'
ORDER BY waiting_for DESC;

等待超过 30 秒即值得人工介入。锁模式语义与冲突关系见《锁冲突矩阵》与《表级锁(ACCESS SHARE / EXCLUSIVE)》,等待超时参数见《锁等待与超时》。

缓存命中率与 I/O ​

数据源:pg_stat_database、pg_statio_user_tables、pg_stat_io(PG16+)。

sql
-- 库级命中率(增量口径更准,此处为累计口径的速查版)
SELECT datname,
       round(100.0 * blks_hit / nullif(blks_hit + blks_read, 0), 2) AS hit_ratio,
       blks_read,
       blks_hit
FROM pg_stat_database
WHERE datname = current_database();

-- 读盘最重的表
SELECT relname,
       heap_blks_read,
       idx_blks_read,
       toast_blks_read
FROM pg_statio_user_tables
ORDER BY heap_blks_read + idx_blks_read DESC
LIMIT 10;

OLTP 基线 99% 上下;突然下降优先排查:新增的全表扫描查询、shared_buffers 容量、大批量报表任务。

表膨胀与死元组 ​

数据源:pg_stat_user_tables;精确测量用 pgstattuple。

sql
-- 死元组占比粗估(估算值,用于发现趋势)
SELECT relname,
       n_live_tup,
       n_dead_tup,
       round(100.0 * n_dead_tup /
             nullif(n_live_tup + n_dead_tup, 0), 1) AS dead_pct,
       last_autovacuum,
       autovacuum_count
FROM pg_stat_user_tables
WHERE n_dead_tup > 10000
ORDER BY n_dead_tup DESC
LIMIT 20;

-- autovacuum 长期未光顾的热表
SELECT relname, n_dead_tup, last_autovacuum, last_autoanalyze
FROM pg_stat_user_tables
WHERE n_live_tup > 100000
  AND (last_autovacuum IS NULL OR last_autovacuum < now() - interval '7 days')
ORDER BY n_dead_tup DESC;

膨胀的判定标准、精确测量与处置手段见《表膨胀检测与处理》;autovacuum 参数调优见《AutoVacuum 配置》。

未使用与低效索引 ​

数据源:pg_stat_user_indexes、pg_statio_user_indexes。

sql
-- 零使用索引候选(需覆盖完整业务周期后再决策)
SELECT s.relname,
       s.indexrelname,
       pg_size_pretty(pg_relation_size(s.indexrelid)) AS size,
       s.idx_scan,
       pg_get_indexdef(s.indexrelid) AS index_def
FROM pg_stat_user_indexes s
WHERE s.idx_scan = 0
  AND NOT EXISTS (SELECT 1 FROM pg_constraint c WHERE c.conindid = s.indexrelid)
ORDER BY pg_relation_size(s.indexrelid) DESC;

-- 顺序扫描大户(缺索引信号)
SELECT relname,
       seq_scan,
       seq_tup_read,
       round(seq_tup_read::numeric / nullif(seq_scan, 0)) AS rows_per_scan
FROM pg_stat_user_tables
WHERE seq_scan > 100
ORDER BY seq_tup_read DESC
LIMIT 10;

判定流程与删索引的注意事项见《索引使用监控》;本查询与索引专题页的差异仅在于「巡检口径」的取巧。

WAL 产生量与检查点 ​

数据源:pg_stat_wal(PG14+)、pg_stat_checkpointer(PG17+)/pg_stat_bgwriter。

sql
-- WAL 累计产生量(增量采样后为速率)
SELECT wal_records,
       wal_fpi,
       pg_size_pretty(wal_bytes::bigint) AS wal_total,
       wal_buffers_full
FROM pg_stat_wal;

-- 实时 WAL 位置(计算单位时间增量)
SELECT pg_current_wal_lsn(),
       pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), '0/0')) AS total_wal_since_start;

-- psql 采样两点的增量(\gset 存下起点,隔时再算差值)
SELECT pg_current_wal_lsn() AS start_lsn \gset

-- 15 秒后执行:
SELECT pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), :'start_lsn')) AS wal_per_15s;

WAL 速率决定归档带宽与备份恢复时长;wal_buffers_full 持续增长提示 WAL 缓冲区偏小。检查点参数的配套调优见《WAL 与检查点优化》。

归档延迟 ​

数据源:pg_stat_archiver;归档配置见《WAL 归档配置(archive_mode / archive_command)》。

sql
SELECT archived_count,
       last_archived_wal,
       last_archived_time,
       failed_count,
       last_failed_wal,
       last_failed_time,
       round(extract(epoch FROM (now() - last_archived_time))::numeric, 0) AS seconds_since_archive
FROM pg_stat_archiver;
sql
-- 归档落后多少 WAL(字节)
SELECT pg_size_pretty(
    pg_wal_lsn_diff(pg_current_wal_lsn(), last_archived_wal::pg_lsn)
) AS archive_lag_bytes,
   last_archived_wal
FROM pg_stat_archiver
WHERE last_archived_wal IS NOT NULL;

告警建议:seconds_since_archive 超过归档周期倍数、failed_count 增长、archive_lag_bytes 超过阈值,三者任一触发都要检查归档目标存储与 archive_command 的退出码。

复制延迟 ​

数据源:pg_stat_replication(主库执行);完整语义见《pg_stat_replication 监控》。

sql
SELECT application_name,
       state,
       sent_lsn,
       replay_lsn,
       pg_size_pretty(pg_wal_lsn_diff(sent_lsn, replay_lsn)) AS replay_lag_bytes,
       write_lag,
       flush_lag,
       replay_lag
FROM pg_stat_replication;

replay_lag(时间)与 pg_wal_lsn_diff(字节)双口径监控:前者对业务直观,后者在延迟突变时更可靠。备机侧还能结合 pg_last_wal_replay_lsn() 与备库 pg_stat_database_conflicts 一起看。

Top SQL 采样 ​

数据源:pg_stat_statements;字段语义见《pg_stat_statements SQL 统计》。

sql
SELECT round(total_exec_time::numeric / 1000, 1) AS total_sec,
       calls,
       round(mean_exec_time::numeric, 2) AS mean_ms,
       round((100 * total_exec_time / sum(total_exec_time) OVER ())::numeric, 1) AS pct,
       left(query, 80) AS query_head
FROM pg_stat_statements
ORDER BY total_exec_time DESC
LIMIT 10;

四个榜单(总耗时、平均耗时、读盘、临时文件)的完整模板见 pg_stat_statements 专题页,本节不重复。

autovacuum 行为监控 ​

autovacuum 是「沉默的清道夫」,出问题的方式是「不干活」而不是「报错」。监控有两个面:

sql
-- 面 1:实时——现在有哪些 worker 在清理什么
SELECT pid,
       datname,
       now() - query_start AS running_for,
       query
FROM pg_stat_activity
WHERE backend_type = 'autovacuum worker'
ORDER BY query_start;

-- 面 2:累计——哪些热表长期没被光顾
SELECT relname,
       n_live_tup,
       n_dead_tup,
       last_autovacuum,
       last_autoanalyze,
       autovacuum_count
FROM pg_stat_user_tables
WHERE n_live_tup > 100000
  AND (last_autovacuum IS NULL OR last_autovacuum < now() - interval '3 days')
ORDER BY n_dead_tup DESC;

判定经验:热表的 autovacuum_count 长期停滞且 n_dead_tup 在涨,先查是不是有长事务压住了 xmin 水位(pg_stat_activity 的 backend_xmin),再查触发阈值是否过松。参数调优见《AutoVacuum 配置》,膨胀处置见《表膨胀检测与处理》。

事务 ID 冻结水位巡检 ​

事务 ID 是 32 位循环使用的资源,冻结(FREEZE)水位过高会触发激进清理甚至停机保护。巡检分两层:

sql
-- 库级水位:距保护线的余量
SELECT datname,
       age(datfrozenxid) AS db_xid_age,
       round(100.0 * age(datfrozenxid) / 2147483648, 2) AS pct_to_limit
FROM pg_database
ORDER BY db_xid_age DESC;

-- 表级水位:找出拖后腿的表
SELECT c.oid::regclass AS table_name,
       age(c.relfrozenxid) AS table_xid_age,
       pg_size_pretty(pg_total_relation_size(c.oid)) AS total_size
FROM pg_class c
JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE c.relkind IN ('r', 'm')
  AND n.nspname NOT IN ('pg_catalog', 'information_schema')
ORDER BY age(c.relfrozenxid) DESC
LIMIT 10;

健康线建议:库级 age 常态低于 2 亿、表级低于 10 亿;任何逼近 20 亿的读数都是 P0 事件。冻结的完整机理(水位为什么会停滞、autovacuum_freeze_max_age 的作用、强制流程)见《冻结事务 ID(FREEZE)》。

临时文件专项巡检 ​

临时文件是「慢查询的外部证据」:排序、哈希、物化溢出内存时都会落盘。专项巡检三步:

sql
-- 1) 库级:历史累计(采样取增量才有速率意义)
SELECT datname, temp_files, pg_size_pretty(temp_bytes) AS temp_total
FROM pg_stat_database WHERE temp_files > 0;

-- 2) 语句级:谁在制造溢出
SELECT calls, temp_blks_written, left(query, 80) AS query_head
FROM pg_stat_statements
ORDER BY temp_blks_written DESC LIMIT 5;

-- 3) 实时:正在长时间运行的会话(结合 IO 等待事件判断是否在写临时文件)
SELECT pid, usename, now() - query_start AS duration,
       wait_event_type, wait_event, left(query, 60) AS query_head
FROM pg_stat_activity
WHERE state = 'active' AND backend_type = 'client backend'
ORDER BY query_start;

处置顺序永远是「先优化语句、再按角色调 work_mem」,见《work_mem 工作内存》。磁盘上的临时文件本体(base/pgsql_tmp)在语句结束后即删除;巡检发现的「残留目录」通常对应被 cancel 掉的长查询,确认后可手工清理。

通用增量采样模板 ​

把前文的采样思路升级为一份可复用的模板——任何累计型指标接入只需两行:

sql
-- 模板:把某个累计值记一笔(monitor_snapshots 表结构见基础概念一节)
INSERT INTO monitor_snapshots (metric, value)
SELECT 'pg_stat_wal.wal_bytes', wal_bytes FROM pg_stat_wal;

INSERT INTO monitor_snapshots (metric, value)
SELECT 'archiver.failed_count', failed_count FROM pg_stat_archiver;
sql
-- 速率视图:差值计算做成一张视图,新指标自动获得速率
CREATE VIEW monitor_rates AS
SELECT metric,
       taken_at,
       value - lag(value) OVER (PARTITION BY metric ORDER BY taken_at) AS delta,
       taken_at - lag(taken_at) OVER (PARTITION BY metric ORDER BY taken_at) AS interval
FROM monitor_snapshots;

监控系统(postgres_exporter 配合 Prometheus 等)内部做的正是这件事。自建方案时,把「指标注册 + 差值视图」标准化,新指标的接入成本趋近于零。

表级块 I/O:pg_statio_user_tables 补充巡检 ​

命中率巡检到表级就靠 pg_statio_user_tables,它与 pg_stat_user_tables 同构、专注于块读数:

sql
SELECT relname,
       heap_blks_read,
       heap_blks_hit,
       round(100.0 * heap_blks_hit /
             nullif(heap_blks_hit + heap_blks_read, 0), 1) AS heap_hit_pct,
       idx_blks_read,
       idx_blks_hit
FROM pg_statio_user_tables
WHERE heap_blks_hit + heap_blks_read > 100000
ORDER BY heap_blks_read DESC
LIMIT 10;

解读要点:heap_blks_read 高且命中率低的表是「全表扫描大户」(与 seq_scan 高的表交叉印证);idx_blks_read 高则说明索引本身没被缓存住(索引偏大或访问稀疏)。块级数字同样要采样取增量,累计值只有排名意义。

实战示例 ​

示例一:一条查询的「全库体检」 ​

把多个关键指标拼进一条结果,适合接入监控系统的自定义 SQL 检查:

sql
SELECT
    (SELECT count(*) FROM pg_stat_activity
     WHERE backend_type = 'client backend') AS conns,
    (SELECT count(*) FROM pg_stat_activity
     WHERE state = 'idle in transaction'
       AND backend_type = 'client backend') AS idle_tx,
    (SELECT count(*) FROM pg_stat_activity
     WHERE wait_event_type = 'Lock'
       AND backend_type = 'client backend') AS lock_waiters,
    (SELECT max(now() - xact_start) FROM pg_stat_activity
     WHERE xact_start IS NOT NULL) AS oldest_xact,
    (SELECT round(100.0 * blks_hit /
             nullif(blks_hit + blks_read, 0), 2)
     FROM pg_stat_database WHERE datname = current_database()) AS hit_ratio,
    (SELECT deadlocks FROM pg_stat_database
     WHERE datname = current_database()) AS deadlocks,
    (SELECT coalesce(max(pg_wal_lsn_diff(sent_lsn, replay_lsn)), 0)
     FROM pg_stat_replication) AS max_replay_lag_bytes;

输出一行七个指标,任何一列越界都是分诊线索——这是应急值班「先看一行再深挖」的入口查询。

示例二:bash 巡检脚本骨架 ​

bash
#!/usr/bin/env bash
# monitor.sh —— 每分钟采集核心指标并追加到 CSV
PGHOST=127.0.0.1 PGPORT=5432 PGUSER=monitor PGDATABASE=appdb

psql -At -F ',' -c "
SELECT now(),
       (SELECT count(*) FROM pg_stat_activity WHERE backend_type='client backend'),
       (SELECT count(*) FROM pg_stat_activity WHERE state='idle in transaction'),
       (SELECT count(*) FROM pg_stat_activity WHERE wait_event_type='Lock'),
       (SELECT round(100.0*blks_hit/nullif(blks_hit+blks_read,0),2)
          FROM pg_stat_database WHERE datname=current_database()),
       pg_wal_lsn_diff(pg_current_wal_lsn(),'0/0');
" >> /var/log/pg_monitor/metrics.csv 2>&1
text
2026-09-30 10:00:01.234+08,58,0,2,99.41,184022135
2026-09-30 10:01:01.301+08,61,1,2,99.40,184063209

对比两行的 WAL 偏移差即可得到每分钟 WAL 增量。生产化建议:用监控系统的 exporter 代替裸脚本,脚本仅作为没有监控体系时的兜底。

示例三:告警 SQL 清单 ​

下表汇总本页各查询对应的告警阈值建议,供监控系统配置参考:

指标查询来源建议阈值处置方向
连接使用率连接总览> 80%扩容连接池 / max_connections
idle in transaction 数量长事务查询> 0 持续 5 分钟定位应用未提交事务
最老事务年龄长事务查询> 30 分钟确认业务后终止会话
锁等待数阻塞链查询等待 > 30 秒处理阻塞源头
命中率命中率查询相对基线下降 > 1%查新增扫描 / 缓存容量
死元组占比膨胀粗估> 20% 且持续增长检查 autovacuum / 长事务
零使用索引未使用索引观察满一个业务周期三重验证后删除
WAL 速率WAL 采样超过归档带宽 80%扩归档带宽 / 降 WAL 生成
归档延迟pg_stat_archiverseconds_since_archive 超周期查归档目标与 archive_command
复制延迟pg_stat_replicationreplay_lag > 10s 或字节超阈值查网络 / 备机 IO / 长查询
死锁计数pg_stat_database计数增长日志定位加锁顺序
事务 ID 水位冻结水位巡检age(datfrozenxid) > 2 亿排查长事务 / 调冻结参数
autovacuum 停滞autovacuum 行为监控热表 3 天无 autovacuum 且死元组增长查 xmin 水位 / 调触发阈值
临时文件速率临时文件专项temp_bytes 增速超基线优化语句 / 调 work_mem

阈值是起点不是终点,所有阈值都应该按各自基线校准。

示例四:故障复盘时的组合取证 ​

假设某天凌晨出现连接耗尽告警,复盘取证顺序:

sql
-- 1. 谁占着连接(结合监控历史的时间点)
SELECT client_addr, application_name, usename, state, count(*)
FROM pg_stat_activity
WHERE backend_type = 'client backend'
GROUP BY 1,2,3,4 ORDER BY count(*) DESC;

-- 2. 当时是否被锁放大(存活证据已消失,改看日志与计数)
SELECT deadlocks FROM pg_stat_database WHERE datname = current_database();

-- 3. 当时有没有超长事务残留(backend_xmin 停滞的证据看膨胀趋势)
SELECT relname, n_dead_tup, last_autovacuum
FROM pg_stat_user_tables
ORDER BY n_dead_tup DESC LIMIT 5;

-- 4. SQL 层面有没有异常波峰(对比 pg_stat_statements 采样历史)
SELECT calls, mean_exec_time, left(query, 80)
FROM sql_stats_history
WHERE captured_at BETWEEN '2026-09-30 01:50' AND '2026-09-30 02:10'
ORDER BY calls DESC LIMIT 10;

「实时视图已消失、累计统计还在」是复盘的铁律:这也是为什么最佳实践反复强调采样落库。

示例五:冻结水位巡检脚本 ​

把水位巡检做成每周报告,附上趋势:

bash
#!/usr/bin/env bash
# xid_age_report.sh —— 每周输出库级与表级水位 Top 10
echo '---- databases ----'
psql -X -At -F '|' -c "
SELECT datname, age(datfrozenxid)
FROM pg_database ORDER BY 2 DESC LIMIT 10;"
echo '---- tables ----'
psql -X -At -F '|' -c "
SELECT c.oid::regclass::text, age(c.relfrozenxid)
FROM pg_class c JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE c.relkind IN ('r','m') AND n.nspname NOT IN ('pg_catalog','information_schema')
ORDER BY 2 DESC LIMIT 10;"
text
---- databases ----
appdb|214003118
reportdb|89412204
---- tables ----
public.events|201842207
public.orders|188402113

读法:库级 2.14 亿属于「关注」区间(超过 5 亿进入「处置」区间);表级前两名与库级水位接近,说明它们是冻结进度的瓶颈——检查这两张表上是否有长事务或复制槽压住 xmin 水位,或对它们在低峰手动 VACUUM FREEZE。历史趋势与处置细节见《冻结事务 ID(FREEZE)》。

注意事项 ​

累计指标必须做增量。 本页凡是从 pg_stat_database、pg_stat_wal、pg_stat_archiver、pg_stat_user_tables 读数的查询,生产使用时都要换成「两次采样相减」的增量口径,直接对累计值告警会天天误报。

实时视图在高负载下有查询成本。 pg_blocking_pids 与 pg_locks 的复杂自连接在数千连接的实例上不便宜,巡检频率与实例规模要匹配,给监控会话设置 statement_timeout 兜底。

监控账号权限最小化。 pg_read_all_stats 足以覆盖本页全部查询;个别需要终止会话的应急操作,单独授予带函数白名单的更高权限,不与日常巡检混用。

估算值与精确值分开用。 n_dead_tup、n_live_tup 是估算值,适合趋势告警;做删除/重建决策前用 pgstattuple 精确复核,避免基于误差数据动刀。

跨版本字段差异。 pg_stat_wal(PG14+)、pg_stat_io(PG16+)、pg_stat_checkpointer(PG17+)、sessions_*(PG14+)都有版本门槛,写通用脚本前用 pg_get_viewdef 或版本判断做能力探测。

查询文本包含敏感信息。 pg_stat_activity.query 与 pg_stat_statements.query 可能含业务数据片段,巡检结果落库、截图、贴群都要注意脱敏(参考《数据脱敏方案》的思路)。

复制相关查询有主备之分。 pg_stat_replication 只在主库有数据;归档统计 pg_stat_archiver 只在开启归档的实例上有意义;备库查询冲突要看备库自己的 pg_stat_database_conflicts。

最佳实践 ​

  1. 把本页查询整理成三个清单接入系统:分钟级采集、小时级巡检、应急手册。 分层的意义在于成本与灵敏度的匹配,而不是所有查询都以最高频率跑。
  2. 所有累计指标走增量采样框架。 统一的快照表结构 + 速率计算,让新指标接入成本趋近于零。
  3. 每条告警都绑定处置手册链接。 告警消息里写清楚「查询来源 + 对应专题页」,值班人员不用现场翻文档。
  4. 阈值按基线校准,按季度回顾。 业务增长会让老阈值失效;用监控数据的分位数(P95)自动建议阈值比拍脑袋可靠。
  5. 巡检结果落历史表,哪怕监控系统能画图。 「实时视图消失、历史表还在」是复盘的底气,轻量快照表的存储成本可以忽略。
  6. 定期跑零使用索引与表膨胀两个报告。 这两项是「慢性病」,不会突发告警,但月度巡检能避免几年后的大手术。
  7. 应急入口固定为「一行体检」查询。 值班时先跑示例一的七个指标,再按异常列跳转对应专题页,减少现场决策成本。
  8. 敏感字段出报告前先脱敏。 query 文本、application_name、client_addr 组合起来可能定位到具体业务与用户,报告外发统一过脱敏流程。
  9. 升级大版本后重跑一遍全清单。 新版本新增字段(如 pg_stat_io)值得加入采集,旧字段语义偶有调整,全清单重跑是最便宜的回归验证。
  10. 把 SQL 与阈值纳入版本管理。 巡检脚本、快照表结构、告警阈值随代码一起 review,避免「线上监控配置无人知晓」的漂移。

参考链接 ​