由 John Doe 九月 30, 2025
你想要知道 PostgreSQL 中哪个后端进程的 WAL 生成量较大吗?现在,PostgreSQL 提供了后端 WAL 统计功能。
特性提交日志
为后端统计添加 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