记一次GaussDB监控采集排错案例 【玩转华为云】

举报
Jack20 发表于 2025/09/22 13:38:49 2025/09/22
【摘要】 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
 
 
从报错信息和背景来看,核心问题是GaussDB 与 PostgreSQL 在复制相关系统函数上存在差异,导致监控工具(gaussdb_exporter)使用的 PostgreSQL 风格函数在 GaussDB 中不被支持。

一、问题的根因:GaussDB 与 PostgreSQL 的函数差异

  1. pg_last_wal_receive_lsn()是 PostgreSQL 特有函数
  2. 该函数用于获取备库(处于恢复模式)最后接收的 WAL(Write-Ahead Log)位置,是 PostgreSQL 9.6 及以上版本的内置函数(早期版本使用pg_last_xlog_receive_lsn(),因 PostgreSQL 10 将 XLOG 重命名为 WAL)。
  3. GaussDB 不支持该函数
  1. 您使用的 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 即可。

三、版本差异说明

  1. GaussDB 与 PostgreSQL 的基础版本关联
  2. 您使用的 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 不支持该函数符合其版本定位。
  3. GaussDB 的复制机制特点
  1. GaussDB 的主备复制依赖自有逻辑(如日志复制、一致性校验),更倾向于通过pg_stat_replication(主库视图)、pg_stat_slave_replication(备库视图,部分版本有)等视图暴露状态,而非独立函数。这也是改造时优先使用视图字段的原因。

四、总结一下下

问题根因是GaussDB 不支持 PostgreSQL 的pg_last_wal_receive_lsn()函数,需通过查询系统视图(如pg_stat_replicationreceive_lsn字段)替代。核心解决方案是:
  1. 修改监控 SQL,用 GaussDB 的视图字段替换 PostgreSQL 特有函数;
  2. 确认pg_stat_replication等视图的字段存在性,确保 LSN 计算逻辑正确;
  3. 调整 gaussdb_exporter 的查询模板,适配 GaussDB 的复制指标采集方式。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。