记一次GaussDB监控采集排错案例 【玩转华为云】
【摘要】 collector在尝试采集replication、replication_slot指标时失败了,报错信息如下:time=2025-09-05T09:34:16.375+08:00 level=ERROR source=collector.go:207 msg="collector failed" name=replication duration_seconds=0.0711601 err...
collector在尝试采集replication、replication_slot指标时失败了,报错信息如下:
time=2025-09-05T09:34:16.375+08:00 level=ERROR source=collector.go:207 msg="collector failed" name=replication duration_seconds=0.0711601 err="ERROR: Function pg_last_wal_receive_lsn() does not exist. (SQLSTATE 42883)"
time=2025-09-05T09:34:16.674+08:00 level=INFO source=namespace.go:235 msg="error finding namespace" err="Error running query on database \"113.44.80.136:8000\": pg_stat_replication ERROR: Function pg_last_wal_receive_lsn() does not exist. (SQLSTATE 42883)"
time=2025-09-05T09:34:16.711+08:00 level=INFO source=namespace.go:235 msg="error finding namespace" err="Error running query on database \"113.44.80.136:8000\": pg_replication_slots ERROR: Function pg_last_wal_receive_lsn() does not exist. (SQLSTATE 42883)"
time=2025-09-05T09:34:16.755+08:00 level=ERROR source=collector.go:207 msg="collector failed" name=replication_slot duration_seconds=0.4515532 err="ERROR: Function pg_last_wal_receive_lsn() does not exist. (SQLSTATE 42883)"
time=2025-09-11T15:33:59.609+08:00 level=ERROR source=gaussdb_exporter.go:684 msg="error scraping dsn" err="queryNamespaceMappings errors encountered, namespace: pg_stat_replication error: Error running query on database \"113.44.80.136:8000\": pg_stat_replication ERROR: Function pg_last_wal_receive_lsn() does not exist. (SQLSTATE 42883), namespace: pg_replication_slots error: Error running query on database \"113.44.80.136:8000\": pg_replication_slots ERROR: Function pg_last_wal_receive_lsn() does not exist. (SQLSTATE 42883)" dsn="gaussdb://root:PASSWORD_REMOVED@113.44.80.136:8000/circle_test?sslmode=disable"
相关SQL:
SELECT
*,
(CASE pg_is_in_recovery () WHEN 't' THEN pg_last_wal_receive_lsn () ELSE pg_current_wal_lsn () END) AS pg_current_wal_lsn,
(
CASE
pg_is_in_recovery ()
WHEN 't' THEN
pg_wal_lsn_diff (pg_last_wal_receive_lsn (), PG_LSN ('0/0')) :: FLOAT
ELSE
pg_wal_lsn_diff (pg_current_wal_lsn (), PG_LSN ('0/0')) :: FLOAT
END
) AS pg_current_wal_lsn_bytes,
(
CASE
pg_is_in_recovery ()
WHEN 't' THEN
pg_wal_lsn_diff (pg_last_wal_receive_lsn (), replay_lsn) :: FLOAT
ELSE
pg_wal_lsn_diff (pg_current_wal_lsn (), replay_lsn) :: FLOAT
END
) AS pg_wal_lsn_diff
FROM
pg_stat_replication;
SELECT
slot_name,
DATABASE,
active,
(CASE pg_is_in_recovery () WHEN 't' THEN pg_wal_lsn_diff (pg_last_wal_receive_lsn (), restart_lsn) ELSE pg_wal_lsn_diff (pg_current_wal_lsn (), restart_lsn) END) AS pg_wal_lsn_diff
FROM
pg_replication_slots;
SELECT
slot_name,
slot_type,
CASE
WHEN pg_is_in_recovery () THEN
pg_last_wal_receive_lsn () - '0/0'
ELSE
pg_current_wal_lsn () - '0/0'
END AS current_wal_lsn,
0 AS confirmed_flush_lsn,
active
FROM
pg_replication_slots;
错误提示很明确:SQL查询中引用了名为 pg_last_wal_receive_lsn() 的函数,但该函数在数据库系统中不存在。
GaussDB版本是:gaussdb (GaussDB Kernel 505.2.1 build ff07bff6) compiled at 2024-12-27 09:22:42 commit 10161 last mr 21504 release
采集工具是:Prometheus gaussdb_exporter
采集工具是:Prometheus gaussdb_exporter
从报错信息和背景来看,核心问题是GaussDB 与 PostgreSQL 在复制相关系统函数上存在差异,导致监控工具(gaussdb_exporter)使用的 PostgreSQL 风格函数在 GaussDB 中不被支持。
一、问题的根因:GaussDB 与 PostgreSQL 的函数差异
-
pg_last_wal_receive_lsn()
是 PostgreSQL 特有函数 -
该函数用于获取备库(处于恢复模式)最后接收的 WAL(Write-Ahead Log)位置,是 PostgreSQL 9.6 及以上版本的内置函数(早期版本使用
pg_last_xlog_receive_lsn()
,因 PostgreSQL 10 将 XLOG 重命名为 WAL)。 -
GaussDB 不支持该函数
-
您使用的 GaussDB 版本(Kernel 505.2.1)虽然基于 PostgreSQL 开发,但在复制机制的函数实现上有调整,未提供
pg_last_wal_receive_lsn()
。这是典型的 “兼容性差异”——GaussDB 保留了 PostgreSQL 的核心语法,但在部分系统函数(尤其是与底层存储、复制相关的)上做了定制化实现。
二、一些解决方案:适配 GaussDB 的复制指标采集方法
GaussDB 通过系统视图和自有函数提供复制相关信息,需修改监控查询语句,替换
pg_last_wal_receive_lsn()
为 GaussDB 支持的方式。以下是具体改造方案:1. 明确 GaussDB 的复制状态判断与 LSN 获取方式
需求(原 PostgreSQL 函数) | GaussDB 替代方案 | 说明 |
---|---|---|
判断是否为备库(pg_is_in_recovery() ) |
仍可使用pg_is_in_recovery() (GaussDB 兼容该函数) |
返回t 表示备库,f 表示主库 |
备库最后接收的 LSN(pg_last_wal_receive_lsn() ) |
从pg_stat_replication 视图的receive_lsn 字段获取(主库视角);或备库通过pg_stat_get_wal_receive_lsn() 函数(部分版本支持) |
GaussDB 中,备库的接收 LSN 直接记录在复制状态视图中,无需单独函数计算 |
主库当前 WAL 位置(pg_current_wal_lsn() ) |
使用pg_current_wal_lsn() (GaussDB 兼容)或pg_stat_get_wal_current_lsn() 函数 |
主库当前写入的 WAL 位置,与 PostgreSQL 用法一致 |
2. 修改监控 SQL 语句(核心改造)
针对您提供的 3 条 SQL,替换
pg_last_wal_receive_lsn()
为 GaussDB 支持的方式:(1)第一条 SQL(pg_stat_replication
查询)
原 SQL 问题:备库判断分支使用了
pg_last_wal_receive_lsn()
,GaussDB 不支持。改造后:
SELECT
*,
-- 替换备库LSN获取方式:主库用pg_current_wal_lsn(),备库从pg_stat_replication取receive_lsn
(CASE pg_is_in_recovery ()
WHEN 't' THEN (SELECT receive_lsn FROM pg_stat_replication LIMIT 1) -- 备库场景
ELSE pg_current_wal_lsn ()
END) AS pg_current_wal_lsn,
(
CASE
pg_is_in_recovery ()
WHEN 't' THEN
-- 备库:计算receive_lsn与0/0的差值
pg_wal_lsn_diff ((SELECT receive_lsn FROM pg_stat_replication LIMIT 1), PG_LSN ('0/0')) :: FLOAT
ELSE
-- 主库:沿用原逻辑
pg_wal_lsn_diff (pg_current_wal_lsn (), PG_LSN ('0/0')) :: FLOAT
END
) AS pg_current_wal_lsn_bytes,
(
CASE
pg_is_in_recovery ()
WHEN 't' THEN
-- 备库:用receive_lsn与replay_lsn计算差值
pg_wal_lsn_diff ((SELECT receive_lsn FROM pg_stat_replication LIMIT 1), replay_lsn) :: FLOAT
ELSE
-- 主库:沿用原逻辑
pg_wal_lsn_diff (pg_current_wal_lsn (), replay_lsn) :: FLOAT
END
) AS pg_wal_lsn_diff
FROM
pg_stat_replication;

(2)第二条 SQL(pg_replication_slots
查询)
改造后:
SELECT
slot_name,
database,
active,
(CASE pg_is_in_recovery ()
WHEN 't' THEN
-- 备库:用receive_lsn计算差值
pg_wal_lsn_diff ((SELECT receive_lsn FROM pg_stat_replication LIMIT 1), restart_lsn)
ELSE
-- 主库:沿用原逻辑
pg_wal_lsn_diff (pg_current_wal_lsn (), restart_lsn)
END) AS pg_wal_lsn_diff
FROM
pg_replication_slots;

(3)第三条 SQL(pg_replication_slots
补充查询)
SELECT
slot_name,
slot_type,
CASE
WHEN pg_is_in_recovery () THEN
-- 备库:用receive_lsn与0/0的差值
pg_wal_lsn_diff ((SELECT receive_lsn FROM pg_stat_replication LIMIT 1), PG_LSN ('0/0'))
ELSE
-- 主库:沿用原逻辑
pg_wal_lsn_diff (pg_current_wal_lsn (), PG_LSN ('0/0'))
END AS current_wal_lsn,
0 AS confirmed_flush_lsn,
active
FROM
pg_replication_slots;

3. 验证 GaussDB 的系统视图与函数
执行以下语句确认 GaussDB 支持的字段和函数,确保改造有效:
-- 1. 查看pg_stat_replication视图结构(确认是否有receive_lsn字段)
\d pg_stat_replication;
-- 2. 检查备库LSN相关函数(部分GaussDB版本可能提供)
SELECT pg_stat_get_wal_receive_lsn(); -- 若返回值,则可替代子查询
-- 3. 确认主库当前LSN函数
SELECT pg_current_wal_lsn();
4. 调整 gaussdb_exporter 配置
将修改后的 SQL 更新到 gaussdb_exporter 的查询模板中(通常在
queries.yaml
或代码内置的 SQL 字符串中),重新部署 exporter 即可。三、版本差异说明
-
GaussDB 与 PostgreSQL 的基础版本关联
-
您使用的 GaussDB Kernel 505.2.1 对应的 PostgreSQL 基础版本接近PostgreSQL 9.2/9.3(通过内核特性推断),而
pg_last_wal_receive_lsn()
是 PostgreSQL 9.6 + 引入的(替换了 9.5 及之前的pg_last_xlog_receive_lsn()
)。因此,从基础版本兼容性来看,GaussDB 不支持该函数符合其版本定位。 -
GaussDB 的复制机制特点
-
GaussDB 的主备复制依赖自有逻辑(如日志复制、一致性校验),更倾向于通过
pg_stat_replication
(主库视图)、pg_stat_slave_replication
(备库视图,部分版本有)等视图暴露状态,而非独立函数。这也是改造时优先使用视图字段的原因。
四、总结一下下
问题根因是GaussDB 不支持 PostgreSQL 的
pg_last_wal_receive_lsn()
函数,需通过查询系统视图(如pg_stat_replication
的receive_lsn
字段)替代。核心解决方案是:- 修改监控 SQL,用 GaussDB 的视图字段替换 PostgreSQL 特有函数;
- 确认
pg_stat_replication
等视图的字段存在性,确保 LSN 计算逻辑正确; - 调整 gaussdb_exporter 的查询模板,适配 GaussDB 的复制指标采集方式。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)