pg_stat_activity 默认不采集 query 字段,因其含敏感信息、超长语句、高频变更,易引发安全、性能与存储问题;postgres_exporter 使用精简视图,并推荐 pg14+ 的 query_id 替代原始 query。

pg_stat_activity 为什么默认不采集 query 字段
因为 pg_stat_activity.query 包含正在执行的 SQL 文本,可能含敏感信息、超长语句(几 MB)、高频变更,直接暴露会拖慢 exporter、撑爆 Prometheus 存储、引发安全审计问题。postgres_exporter 默认用 pg_stat_activity 的精简视图(不含 query),只保留 pid、state、backend_start 等低开销字段。
- 若硬要加
query,需手动改custom_queries,且必须配max_length截断(如 200 字符) - PostgreSQL 14+ 支持
pg_stat_activity.query_id,更轻量,建议优先用它做关联分析,而非原始query - 启用
track_activity_query_size参数(默认 1024)才能让query字段有值,否则始终为 NULL
怎么写一个安全可用的 custom\_queries 模板
别直接 SELECT * FROM pg_stat_activity;得过滤、截断、重命名指标名,否则 Prometheus 会拒收(非法字符、重复 label)。下面这个模板能跑通、可监控连接状态和慢查询倾向:
custom_queries:
- name: pg_stat_activity_safe
help: Safe pg_stat_activity metrics without raw query text
metrics:
- pid:
usage: "GAUGE"
description: "Backend process ID"
- state:
usage: "LABEL"
description: "Current overall state of this backend"
- backend_start:
usage: "COUNTER"
description: "Time when this backend process was started"
- state_change:
usage: "COUNTER"
description: "Time when the current backend state was entered"
- application_name:
usage: "LABEL"
description: "Name of the application that is connected to this backend"
- client_hostname:
usage: "LABEL"
description: "Host name of the connected client"
- backend_type:
usage: "LABEL"
description: "Type of current backend"
# 可选:加 query_id,但需 PG >= 14
# - query_id:
# usage: "GAUGE"
# description: "Unique identifier for this query"
query: |
SELECT
pid,
state,
EXTRACT(EPOCH FROM backend_start)::int AS backend_start,
EXTRACT(EPOCH FROM state_change)::int AS state_change,
COALESCE(application_name, '') AS application_name,
COALESCE(client_hostname, '') AS client_hostname,
backend_type,
-- 避免 NULL 导致 label 丢失,统一转空字符串
COALESCE(state, 'unknown') AS state_label
FROM pg_stat_activity
WHERE backend_type IN ('client backend', 'background worker')
AND pid != pg_backend_pid()-
EXTRACT(EPOCH FROM ...)转成整数秒,避免浮点精度问题和 Prometheus 类型冲突 - 所有
COALESCE是防 NULL —— Prometheus label 不接受 NULL 值,会丢整行指标 -
WHERE过滤掉自身 exporter 连接(pid != pg_backend_pid())和非业务 backend,减少噪声 - 如果真要抓 query,加
SUBSTRING(query FROM 1 FOR 200)+COALESCE(..., ''),但务必关掉auto_discover_database或限定 database_whitelist,否则每个 DB 都扫一遍 query,性能崩
常见报错:column \"query\" does not exist 或 invalid type for metric
前者是 PostgreSQL 版本太低(track_activities = off;后者多因字段类型没对齐:比如把 text 字段当 GAUGE 用,或 timestamp 没转成数字。
网奇Eshop商城购物系统:集成国内优秀商城系统的成功元素,采用ASP.NET2.0语言设计开发.傻瓜式的管理模式,强大的后台管理,可添加或定制风格精美的模板,网站广告位任意添加,集成在线支付接口,内置简、繁、英三种语言.系统不断升级,力求尽善尽美.网奇商城的目标是:打造国内最到的商城系统! 升级功能:1.在线备份SQL数据库2.RSS在线订阅器3.整合了支付宝鲜花支付接口。4.整合了网奇E客通在
- 检查
track_activities是否为on(SHOW track_activities) -
pg_stat_activity在不同 PG 版本字段差异大:PG 13 去掉backend_start的timestamp with time zone直接支持,但 PG 10 需显式::timestamptz,否则 exporter 解析失败 - label 字段不能是
NULL,也不能含换行符或控制字符 ——REPLACE(REPLACE(application_name, '\n', ' '), '\r', ' ')更稳妥 - 如果用
query_id,注意它在 PG 14+ 才稳定,且需pg_stat_statements扩展配合才可反查 SQL 内容
为什么加了 custom\_queries 却看不到新指标
postgres_exporter 不会自动 reload 配置;改完 custom_queries 必须重启进程,或者发 SIGHUP(前提是启动时加了 --web.enable-lifecycle 并用 HTTP POST /-/reload)。
- 确认日志里有没有
Loaded custom queries from ...,没有就是路径错或 YAML 格式非法(尤其注意缩进和冒号后空格) - 访问
http://localhost:9187/metrics搜pg_stat_activity_safe,看是否出现 —— 不出现基本是配置没生效或查询返回空结果集 - 指标名前缀是
name字段值(如pg_stat_activity_safe_pid),不是表名;别在 Prometheus 里搜pg_stat_activity_pid - 如果查询本身慢(比如 JOIN 多张系统表),exporter 会超时(默认 10s),导致该次 scrape 全部失败,日志报
timeout exceeded—— 加statement_timeout = '5s'到查询开头
最麻烦的其实是 label 组合爆炸:比如 application_name 每个微服务实例都带随机后缀,会导致 series 数量失控。上线前一定用 count by (__name__) ({__name__=~"pg_stat_activity_safe_.+"}) 在 Prometheus 里看 cardinality。









