PostgreSQL 18: 获取后端 WAL 统计信息的函数 pg_stat_get_backend_wal

John Doe 九月 30, 2025

你想要知道 PostgreSQL 中哪个后端进程的 WAL 生成量较大吗?现在,PostgreSQL 提供了后端 WAL 统计功能。

image

特性提交日志

为后端统计添加 WAL 数据。

本次提交新增了后端级 WAL 日志的统计功能,其提供的信息与pg_stat_wal(PostgreSQL 全局 WAL 统计视图)一致,不同之处在于:如今可查看每个后端进程各自的 WAL 活动量,而非所有进程 WAL 活动的整体聚合数据。与pg_stat_wal类似,该功能的实现依赖pgWalUsage(PostgreSQL 内置的 WAL 用量计数器),通过计算两次向 PostgreSQL 统计系统上报 WAL 活动的用量差值来实现统计。

可通过新增的系统函数pg_stat_get_backend_wal()获取该统计数据,此函数会根据输入的进程 ID(PID)返回一条对应的统计记录。与pg_stat_get_backend_io()(后端级 IO 统计函数)类似,将该函数与pg_stat_activity(后端活动视图)关联使用时,可实时掌握每个运行中后端进程生成的 WAL 情况,清晰呈现各进程 WAL 活动的分布状态。

pgstat_flush_backend()函数新增了一个标志值,能够控制 WAL 统计数据的刷新操作。

讨论:https://postgr.es/m/Z3zqc4o09dM/Ezyz@ip-10-97-1-34.eu-west-3.compute.internal

为什么需要后端级 WAL 统计?

WAL 预写日志是 PostgreSQL 保障数据一致性的核心机制,所有数据修改操作(如 INSERT/UPDATE/DELETE)都会生成 WAL 记录。在该特性之前,PostgreSQL 的 WAL 统计依赖pg_stat_wal视图,但存在明显局限:

  • 全局聚合,无法定位源头pg_stat_wal展示的是全系统所有进程的 WAL 总消耗(如 WAL 记录数、字节数),若出现 WAL 风暴(WAL 生成量骤增),无法判断是哪个具体进程(如批量数据导入、复杂事务)导致的;
  • 业务与系统 WAL 混淆:检查点进程(checkpointer)、后台写进程(bgwriter)等辅助进程的 WAL 活动,与普通业务后端的 WAL 活动混在一起,难以区分系统与业务的 WAL 开销;
  • 缺乏进程级评估能力:优化 SQL 或调整配置时(如执行存储过程、修改wal_compression ),无法精准评估单个进程的 WAL 生成变化,只能依赖全局统计,易受其他进程干扰。

本次提交的后端级 WAL 统计恰好解决了这些问题。它为每个普通后端进程(业务连接对应的进程)新增 WAL 统计条目,实现了进程级 WAL 消耗的透明化,让 WAL 监控实现了精准定位能力。

示例

本次提交的核心是新增pg_stat_get_backend_wal函数,用于按进程 PID 获取 WAL 统计数据,设计上与 pg_stat_get_backend_io 高度一致,确保使用体验连贯。

在系统 WAL 生成量骤增(WAL 风暴)的情况下,需快速找到消耗最高的进程。

当监控发现 WAL 归档 / 流复制延迟骤增(如pg_stat_replication视图中的replay_lag变大),可通过以下步骤定位源头:

-- 关联 pg_stat_activity 与 pg_stat_get_backend_wal,获取各进程的 WAL 消耗
SELECT
  a.pid,                      -- 后端进程 ID
  a.usename,                  -- 连接用户(区分业务账号)
  a.application_name,         -- 应用名称(如订单系统、报表系统)
  a.query,                    -- 当前执行的 SQL(若进程正运行查询)
  a.wait_event,               -- 等待事件(判断是否因 WAL 阻塞)
  -- 提取该进程的 WAL 核心指标
  wal.wal_records,
  wal.wal_bytes,              -- 重点关注:WAL 总字节数(反映消耗规模)
  wal.wal_buffers_full        -- 重点关注:WAL 缓冲区写满次数(判断是否需调大 wal_buffers)
FROM pg_stat_activity a
-- 左连接当前进程的 WAL 统计(仅保留普通业务后端)
LEFT JOIN pg_stat_get_backend_wal(a.pid) wal ON true
WHERE 
  a.backend_type = 'backend'  -- 排除辅助进程
  AND wal.wal_bytes > 0       -- 仅保留有 WAL 消耗的进程
-- 按 WAL 字节数降序,取前 5 个“WAL 消耗大户”
ORDER BY wal.wal_bytes DESC
LIMIT 5;
  • 若某进程的wal_bytes远高于其他进程(如占比超过 50%),且对应query是批量插入(如INSERT INTO ... SELECT)或大表更新,则该进程是 WAL 风暴的源头;
  • wal_buffers_full数值较高(如超过 100),说明wal_buffers配置过小,需调整wal_buffers参数(如从 16MB 增至 64MB)。

非常不错的新特性,这将会给运维人员的工作带来很多方便。感谢社区的所有相关人员。

参考

提交日志:https://git.postgresql.org/pg/commitdiff/76def4cdd7c2b32d19e950a160f834392ea51744