1. 生产监控体系总览

PostgreSQL 在生产环境中的监控,目标不是“把能采集的指标都采集一遍”,而是围绕三个问题建立可判断、可追溯、可行动的观测能力:数据库现在是否健康、业务体验是否正在变差、按当前增长趋势还能撑多久。前两个问题属于运行监控,第三个问题属于容量规划。三者共用同一套数据源,只是观察窗口和判断标准不同。

很多团队第一次搭建监控时,习惯从“CPU 高不高、内存够不够”入手,结果告警频繁却难以定位。PostgreSQL 的性能瓶颈往往不在主机层,而在等待事件、锁竞争、I/O 延迟、连接数、复制延迟和事务年龄这些数据库内部状态上。因此,监控体系应当按层次组织,而不是按工具罗列。

监控的四个层次

第一层是实例可用性:进程是否存活、端口是否可连接、能否执行最简单的查询。这一层决定“数据库是否在线”,通常用 pg_isready 或一条 SELECT 1 探测即可,采集频率可以较高,但成本极低。

第二层是资源与吞吐:CPU、内存、磁盘 I/O、网络,以及数据库侧的 TPS、QPS、连接数、缓冲区命中率。这一层回答“系统忙不忙、忙在哪里”。例如 pg_stat_database 提供 xact_commit、blks_hit、blks_read,可以算出缓存命中率;pg_stat_bgwriter 则反映检查点与后台写压力。

第三层是内部状态与等待:当前活跃会话在等什么、有没有长事务、锁是否堆积、复制是否滞后、事务 ID 是否接近回卷。这一层是 PostgreSQL 监控的核心价值所在,也是与通用主机监控最大的区别。典型视图包括 pg_stat_activity、pg_locks、pg_stat_replication、pg_stat_user_tables。

第四层是业务与容量:关键业务 SQL 的响应时间、慢查询趋势、表与索引的增长速度、磁盘剩余可用天数。这一层把数据库指标翻译成业务语言和容量结论,是容量规划的输入。

PostgreSQL 生产监控四层体系与容量规划闭环 ① 实例可用性 pg_isready · SELECT 1 · 连接探测 · 进程存活 判断:在线 / 离线 ② 资源与吞吐 CPU · 内存 · 磁盘 I/O · TPS/QPS · 连接数 · 缓存命中率 判断:忙不忙 / 忙在哪 ③ 内部状态与等待 等待事件 · 锁竞争 · 长事务 · 复制延迟 · 事务 ID 年龄 判断:卡在哪 / 是否危险 ④ 业务与容量 慢查询趋势 · 表/索引增长 · 磁盘剩余天数 · 业务响应时间 判断:还能撑多久 容量结论反馈 → 调整阈值与扩容 闭环关系 监控采集 → 指标判断 → 容量趋势外推 → 扩容/优化决策 → 新基线回写监控阈值 闭环

关键指标分类与采集方式

把指标按“症状指标”和“原因指标”分开,是设计告警规则的关键。症状指标反映用户可感知的恶化,例如查询 P99 延迟上升、连接等待时间变长、复制延迟增大;原因指标解释为什么会恶化,例如锁等待、检查点频繁、临时文件激增、autovacuum 落后。告警应主要基于症状指标触发,原因指标用于定位和根因分析。

采集方式上,PostgreSQL 提供两条主要路径。其一是内置统计视图,通过 SQL 定期抓取,适合 pg_stat_* 系列指标,成本低、语义准确。其二是 pg_stat_statements 扩展,它按归一化 SQL 聚合调用次数、总耗时、行数、共享块读写等,是慢查询分析和容量趋势的核心数据源。启用方式如下:

-- postgresql.conf
shared_preload_libraries = 'pg_stat_statements'
pg_stat_statements.max = 10000
pg_stat_statements.track = all

-- 重启后创建扩展
CREATE EXTENSION pg_stat_statements;

-- 查看累计耗时最高的语句
SELECT queryid, calls, total_exec_time, mean_exec_time, rows
FROM pg_stat_statements
ORDER BY total_exec_time DESC
LIMIT 10;

需要注意的是,pg_stat_statements 的统计是累计值,判断趋势时要按时间窗口做差分,而不是直接看总量。例如每 5 分钟采集一次 total_exec_time,两次差值除以 300 秒,才得到该时段的平均每秒执行时间。

工具生态的分工

生产环境通常不会只用一种工具。合理的分工是:Prometheus + postgres_exporter 负责指标采集与长期存储,Grafana 负责可视化与看板,Alertmanager 负责告警路由,pg_stat_statements + 慢查询日志 负责 SQL 级分析,pgBackRest 或 pg_basebackup 的监控 负责备份可用性。工具之间通过统一的时间序列数据衔接,避免各自为政。

postgres_exporter 默认会暴露大量 pg_stat_* 指标,但默认查询并不覆盖所有关键项。生产上通常需要自定义查询,把复制延迟、事务 ID 年龄、锁等待数、autovacuum 进度等纳入采集。例如复制延迟可以用以下查询暴露为指标:

SELECT
  client_addr,
  application_name,
  pg_wal_lsn_diff(pg_current_wal_lsn(), replay_lsn) AS replay_lag_bytes
FROM pg_stat_replication;

容量规划与监控的闭环

容量规划不是一次性估算,而是把监控数据转化为趋势判断的过程。核心做法是:对关键容量指标(数据目录大小、表与索引大小、WAL 生成速率、连接数峰值、磁盘 IOPS)按天或按周取快照,做线性或分段趋势外推,得到“按当前增速,磁盘剩余可用天数”这类可决策结论。

例如,某实例数据目录当前 800 GB,过去 30 天从 650 GB 增长到 800 GB,日均增长约 5 GB,磁盘总容量 1.2 TB,剩余 400 GB。按线性外推,约 80 天后触及容量上限。这个结论会反过来影响监控:把磁盘使用率告警阈值从固定的 85% 调整为“剩余可用天数小于 30 天”,更贴近实际风险。

容量规划的输出应当是可执行的:扩容时间点、需要增加的磁盘或实例规格、需要优化的表或索引、需要调整的参数。没有落到行动项的容量报告,只是数据汇总。

从监控到行动的判断依据

监控体系是否有效,最终看能否在故障发生前给出明确信号。以下是一组常见的判断参考:连接数持续超过 max_connections 的 80% 且伴随等待,说明连接池或规格需要调整;复制延迟持续超过 30 秒,说明网络或从库回放能力不足;最老事务的 xact_start 超过数小时,说明存在长事务阻塞 vacuum;事务 ID 年龄超过 10 亿,需要立即介入防止回卷。

这些阈值不是固定标准,而是需要结合业务容忍度、实例规格和历史基线来校准。监控体系的价值,正在于提供校准所需的数据,并把数据转化为可重复执行的判断规则。