PostgreSQL 出问题时,常常不是突然坏掉,而是早就留下了痕迹:膨胀悄悄增长、复制槽一直扣着 WAL、事务 ID wraparound 接近危险线、备份任务几周前已经停了。pg-healthcheck 想解决的正是这个痛点:用一个开源 Go 工具直接查询 PostgreSQL 系统目录和视图,输出一份可以行动的健康报告。
它覆盖 14 组、180 多项检查,既能跑在单实例 PostgreSQL 上,也支持 pgEdge 多节点 Spock 集群;输出可以是彩色终端报告,也可以是结构化 JSON,方便接进监控、CI 或运维脚本。
它不是“看起来正常”的仪表盘
很多数据库监控停留在 CPU、连接数、磁盘空间这类外部指标。它们有用,但不一定能回答更棘手的问题:
- 哪些表和索引已经膨胀到值得处理?
- 有没有逻辑复制槽正在悄悄拖住 WAL?
- VACUUM 是否被可见性映射或冻结状态问题绊住?
- WAL 生成速率是不是突然比历史基线高出很多?
- TOAST 或 B-tree 结构有没有需要进一步确认的完整性问题?
pg-healthcheck 的定位更像 DBA 的巡检清单:直接从 PostgreSQL 内部状态取数,不靠模拟数据,也不只给一个“红黄绿”灯。每个发现会带上严重级别、观察到的现象、建议动作和相关 PostgreSQL 文档线索。
它的退出码也适合自动化:
0:没有发现明显问题1:存在 WARN2:存在 CRITICAL
这意味着你可以把它放进定时任务、发布前检查、故障响应脚本,甚至作为临时审计工具使用。
最值得盯住的几类检查
14 组检查里,几个高价值方向尤其适合生产环境优先接入。
Vacuum 与膨胀:这组会关注 dead tuples、表膨胀、索引膨胀,以及事务 ID wraparound 距离。wraparound 是 PostgreSQL 里非常典型的“平时安静、爆发致命”的问题,忙碌系统里尤其容易被忽略。
WAL 与复制槽:复制槽滞后、 inactive slot、invalidated slot、逻辑复制 worker 状态、订阅同步状态都会影响磁盘和复制链路。一个无人消费的 replication slot 可能把 pg_wal 撑爆,这是生产事故里很常见的剧本。
WAL 增长速率:比起只看 pg_wal 当前目录大小,工具会维护滚动基线,并在当前速率超过历史平均值 3 倍时告警。这个思路比固定阈值更适合业务波峰明显的数据库。
TOAST 与数据完整性:TOAST 问题不常见,但一旦发生就很难靠普通指标发现。工具会结合访问模式和 amcheck 的 B-tree 结构检查,帮助把少见但严重的问题暴露出来。
Visibility Map 检查:它使用 pg_visibility 扩展里的 pg_check_visible() 和 pg_check_frozen(),检测 VM 与 heap 状态不一致的问题,例如 VM 标记页面为 ALL_FROZEN,但页面里仍有未冻结 tuple。这类问题 VACUUM 不一定能发现,还可能穿过大版本升级继续存在。
更有意思的是 composite alerts:当多个相关检查同时进入 CRITICAL,比如归档异常加上 WAL 生成暴涨,工具会输出组合告警,解释为什么这两个信号叠在一起特别危险。这种上下文判断,通常来自有经验 DBA 的脑内规则。
可以这样接入日常巡检
下面示例假设你已经下载了适合平台的 pg-healthcheck 二进制,并且 PostgreSQL 可以通过标准连接参数访问。需要按你的环境替换主机、端口、用户、库名和密码。
export PGHOST=127.0.0.1
export PGPORT=5432
export PGUSER=postgres
export PGDATABASE=postgres
export PGPASSWORD='change-me'
./pg-healthcheck
如果只想聚焦 WAL 和复制槽,可以运行指定检查组。具体组名和参数以你安装版本的帮助输出为准,实践中建议先看一遍命令帮助:
./pg-healthcheck --help
./pg-healthcheck --groups G09,G14
要把结果接进监控或告警系统,可以输出 JSON,再用 jq 做第一层过滤:
./pg-healthcheck --output json > healthcheck.json
jq '.findings[] | select(.severity == "CRITICAL" or .severity == "WARN")' healthcheck.json
一个很实用的 shell 包装方式是利用退出码,让 CI、cron 或调度系统直接感知风险等级:
#!/usr/bin/env bash
set -euo pipefail
export PGHOST="db.example.internal"
export PGPORT="5432"
export PGUSER="healthcheck"
export PGDATABASE="postgres"
export PGPASSWORD="${PGPASSWORD:?set PGPASSWORD first}"
./pg-healthcheck --output json > /tmp/pg-healthcheck.json
status=$?
case "$status" in
0)
echo "PostgreSQL healthcheck passed"
;;
1)
echo "PostgreSQL healthcheck has warnings"
jq '.findings[] | select(.severity == "WARN")' /tmp/pg-healthcheck.json
;;
2)
echo "PostgreSQL healthcheck has critical findings"
jq '.findings[] | select(.severity == "CRITICAL")' /tmp/pg-healthcheck.json
exit 2
;;
*)
echo "pg-healthcheck failed with unexpected status: $status"
exit "$status"
;;
esac
如果你希望每个环境有不同阈值,可以维护 healthcheck.yaml。下面是一个可改造的配置示例,字段名请以当前版本文档为准:
# healthcheck.yaml
connection:
host: db.example.internal
port: 5432
database: postgres
user: healthcheck
thresholds:
wal_growth_multiplier: 3
replication_slot_lag_mb_warning: 1024
replication_slot_lag_mb_critical: 10240
txid_wraparound_warning_percent: 70
txid_wraparound_critical_percent: 85
output:
format: json
配置优先级很直观:CLI 参数覆盖 YAML,YAML 覆盖内置默认值。这个规则适合把公共阈值放进仓库,把临时排障参数留给命令行。
ask 子命令:把自然语言变成检查组
pg-healthcheck 还有一个很适合临时排障的能力:ask 子命令。你可以用自然语言描述想查什么,工具会映射到一个或多个检查组再执行。
./pg-healthcheck ask "check whether WAL growth and replication slots can fill disk"
它支持三类 LLM provider:本地 Ollama、OpenAI 和 Google Gemini。默认是 Ollama,适合内网或隔离环境;如果 LLM 不可达,或者没有配置 API key,工具会自动退回内置关键词匹配,不会直接崩掉。需要注意的是,LLM 路径和关键词回退路径映射出的检查组可能略有不同,尤其是多概念查询时,LLM 往往会覆盖得更宽。
可以这样用本地 Ollama 做一次面向问题的巡检:
ollama serve &
ollama pull llama3.1
./pg-healthcheck ask "look for vacuum, bloat, wraparound, and WAL risks"
这类能力不应该替代固定巡检策略,但非常适合作为故障响应入口:当你脑子里只有“磁盘涨得快”“复制像是卡了”“VACUUM 不太对劲”这样的症状时,它能帮你少记一些组号。
pgEdge / Spock 集群里的额外价值
对 pgEdge 环境,工具还有专门的 G12 检查组,覆盖 Spock exception logs、冲突计数、DCA counters,以及节点之间基于 spock.progress 的复制 LSN lag。
这类检查的关键不是“能查一个表”,而是会根据当前安装的 Spock schema 做验证:如果某些表或列在当前版本不存在,对应检查会以 INFO 跳过,而不是硬报错。这对多版本、多节点集群很重要,因为巡检工具本身不能成为新的不稳定因素。
落地时别忘了边界
pg-healthcheck 适合做健康诊断和风险暴露,但不应该被当成自动修复系统。建议按下面方式接入:
- 先在只读或低权限巡检账号上跑通,确认需要哪些扩展和 catalog 权限。
- 先输出 JSON 接入观察期,不要第一天就把所有 WARN 变成值班告警。
- 对 WAL、复制槽、wraparound、备份失效这类高风险项设置更高优先级。
- 把
healthcheck.yaml按环境管理,生产、预发、测试不要共享完全相同阈值。 - 对
ask的结果保持工程判断:它适合辅助定位,不适合替代明确的 SLO 和监控规则。
对 PostgreSQL 来说,真正危险的问题往往不是“没有指标”,而是“指标散落在太多地方,没有人把它们连起来”。pg-healthcheck 的价值就在这里:把 DBA 经验、系统目录查询和自动化输出放在一个工具里,让健康检查从偶尔人工巡检,变成可以重复执行的工程流程。