WAL 日志来源分析(tencentdb_wal_stat)

最近更新时间:2026-04-14 15:47:51

我的收藏
云数据库 PostgreSQL 提供 WAL 日志来源分析扩展,本文为您介绍关于 WAL 日志来源分析(tencentdb_wal_stat)扩展的说明及实践。

概述

tencentdb_wal_stat 是云数据库 PostgreSQL 提供的 WAL 日志来源分析扩展,支持在线按 database、schema、table 三个维度统计 WAL 日志的产生量,帮助您快速定位产生大量 WAL 的对象,及时干预避免磁盘空间告急。
核心价值
精准定位:按 database → schema → table 逐层下钻,快速找到 WAL 产生大户。
在线分析:通过 SQL 直接调用,无需离线解析 WAL 文件。
多维聚合:同时展示 RMGR 类型(Heap/Btree/Transaction 等)、FPI 统计等详细信息。
生产安全:只读分析,不影响业务运行。
典型场景
SaaS 多租户环境下,某租户突发大量写入导致 WAL 堆积。
逻辑复制消费端积压,需要找出 WAL 产生量最大的表进行限流。
日常运维监控 WAL 产生趋势,预防磁盘空间问题。

环境要求

项目
要求
云数据库 PostgreSQL 版本
15.x 及以上
扩展版本
tencentdb_wal_stat v1.0
执行权限
pg_tencentdb_superuser 角色成员
执行环境
仅支持在主库(Primary)上执行

安装与验证

安装扩展

CREATE EXTENSION IF NOT EXISTS tencentdb_wal_stat;

验证安装

输入:
SELECT extname, extversion FROM pg_extension
WHERE extname = 'tencentdb_wal_stat';
输出:
extname
extversion
tencentdb_wal_stat
1.0

函数说明

函数

tencentdb_wal_stat(wal_num integer)
RETURNS SETOF record
参数:
参数
类型
范围
说明
wal_num
integer
1 ~ 500
要分析的 WAL 文件数量,数值越大分析范围越广
说明:
wal_num 越大,分析时间越长。建议在业务低峰期执行大范围分析。

输出字段

字段
类型
说明
database_oid
oid
数据库 OID(共享对象和系统级 WAL 为0)
database_name
text
数据库名称
schema_oid
oid
Schema OID
schema_name
text
Schema 名称(仅当前数据库和共享 catalog 可解析)
relation_oid
oid
关系(表/索引)OID
relation_name
text
关系名称(已删除的对象显示为 <filenode:N>
relation_kind
text
关系类型:table index toast sequence matview shared_table shared_index system unknown
rmgr_name
text
WAL 资源管理器名称(Heap、Btree、Transaction 等)
wal_records
bigint
WAL 记录条数
wal_bytes
bigint
WAL 字节数(不含 FPI)
wal_fpi
bigint
Full Page Image(FPI)记录数
wal_fpi_bytes
bigint
FPI 字节数
说明:
WAL 总大小 = wal_bytes + wal_fpi_bytes。FPI 是 checkpoint 后首次修改页面时写入的完整页面副本,通常占 WAL 总量的20%~40%。

常用查询场景

场景一:磁盘告警,快速定位哪个数据库产生了最多 WAL

输入:
-- 按数据库汇总 WAL 产生量(分析最近50个 WAL 文件)
SELECT database_name,
SUM(wal_records) AS total_records,
pg_size_pretty(SUM(wal_bytes + wal_fpi_bytes)::bigint) AS total_size,
ROUND(SUM(wal_bytes + wal_fpi_bytes) * 100.0 /
SUM(SUM(wal_bytes + wal_fpi_bytes)) OVER (), 1) AS pct
FROM tencentdb_wal_stat(50)
GROUP BY database_name
ORDER BY SUM(wal_bytes + wal_fpi_bytes) DESC;
输出:
database_name
total_records
total_size
pct
func_veri
447033
49 MB
79.6
postgres
53164
7812 KB
12.3
business_analysis
8
49 KB
0.1
monitor
7
44 KB
0.1
instance
7
44 KB
0.1
pg_instance
14
34 KB
0.1

场景二:定位到库后,进一步查看哪个 Schema 产生最多 WAL

输入:
-- 按 schema 维度汇总
SELECT database_name, schema_name,
SUM(wal_records) AS total_records,
pg_size_pretty(SUM(wal_bytes + wal_fpi_bytes)::bigint) AS total_size
FROM tencentdb_wal_stat(50)
WHERE database_name = 'func_veri' -- 替换为目标数据库名
AND schema_name IS NOT NULL AND schema_name != ''
GROUP BY database_name, schema_name
ORDER BY SUM(wal_bytes + wal_fpi_bytes) DESC;
输出:
database_name
schema_name
total_records
total_size
func_veri
public
185846
19 MB
func_veri
pg_catalog
9110
2230 KB
func_veri
test_schema
20521
1443 KB
func_veri
pg_toast
190
179 KB

场景三:精确到表级别,找出 WAL 产生量 TOP10的表

输入:
-- 查看产生 WAL 最多的表 TOP10
SELECT database_name, schema_name, relation_name, relation_kind,
wal_records,
pg_size_pretty(wal_bytes::bigint) AS wal_size,
pg_size_pretty(wal_fpi_bytes::bigint) AS fpi_size,
pg_size_pretty((wal_bytes + wal_fpi_bytes)::bigint) AS total_size
FROM tencentdb_wal_stat(50)
WHERE relation_kind IN ('table', 'index')
ORDER BY (wal_bytes + wal_fpi_bytes) DESC
LIMIT 10;
输出:
database_name
schema_name
relation_name
relation_kind
wal_records
wal_size
fpi_size
total_size
func_veri
public
idx_test_orders
table
50000
4932 KB
0 bytes
4932 KB
func_veri
public
idx_test_products
table
30000
3757 KB
0 bytes
3757 KB
func_veri
public
idx_test_orders_pkey
index
50411
3226 KB
0 bytes
3226 KB
func_veri
public
idx_test_orders_customer_id_status_id_product_name_amount_o_idx
index
444
21 KB
3166 kB
3187 KB
func_veri
public
idx_test_products_pkey
index
30246
1935 KB
0 bytes
1935 KB
postgres
pg_catalog
pg_attribute
table
2475
1023 KB
142 kB
1165 KB
func_veri
public
idx_test_customers
table
10000
1034 KB
0 bytes
1034 KB
func_veri
test_schema
orders
table
10000
732 KB
0 bytes
732 KB
func_veri
test_schema
orders_pkey
index
10084
645 KB
0 bytes
645 KB
func_veri
public
idx_test_customers_pkey
index
10084
645 KB
0 bytes
645 KB

场景四:分析 WAL 类型分布(Heap 写入 vs Index 写入)

输入:
-- 按 RMGR 类型查看 WAL 分布
SELECT rmgr_name,
SUM(wal_records) AS total_records,
pg_size_pretty(SUM(wal_bytes)::bigint) AS wal_size,
ROUND(SUM(wal_records) * 100.0 / SUM(SUM(wal_records)) OVER (), 1) AS pct
FROM tencentdb_wal_stat(50)
GROUP BY rmgr_name
ORDER BY SUM(wal_records) DESC;
输出:
rmgr_name
total_records
wal_size
pct
Btree
246781
16 MB
44.9
Heap
229351
25 MB
41.7
Heap2
46408
3726 KB
8.4
Generic
11119
4349 KB
2.0
Transaction
7120
2015 KB
1.3
Sequence
6288
608 KB
1.1
Standby
1737
73 KB
0.3
XLOG
1163
49 KB
0.2
Storage
116
4912 bytes
0.0
CLOG
1
30 bytes
0.0
说明:
Btree 和 Heap 类型占比高说明表写入(INSERT/UPDATE/DELETE)及其关联的索引维护是 WAL 的主要来源。如果 Btree 占比异常高,可考虑减少不必要的索引。

场景五:查看 FPI(Full Page Image)占比

输入:
-- FPI 占比分析
SELECT
pg_size_pretty(SUM(wal_bytes)::bigint) AS wal_data_size,
pg_size_pretty(SUM(wal_fpi_bytes)::bigint) AS fpi_size,
pg_size_pretty(SUM(wal_bytes + wal_fpi_bytes)::bigint) AS total_size,
ROUND(SUM(wal_fpi_bytes) * 100.0 /
NULLIF(SUM(wal_bytes + wal_fpi_bytes), 0), 1) AS fpi_pct
FROM tencentdb_wal_stat(50);
输出:
wal_data_size
fpi_size
total_size
fpi_pct
51MB
11MB
62MB
17.5
说明:
如果 FPI 占比超过40%,可以考虑调大 max_wal_size 来减少 checkpoint 频率,从而降低 FPI 产生量。

运维实战指南

WAL 堆积应急处理流程

当收到磁盘空间告警或发现 WAL 堆积时,按照以下步骤排查:
步骤1: 查看整体 WAL 产生概况
└── tencentdb_wal_stat(50)database 汇总
步骤2: 定位目标数据库
└── 按 schema 汇总,找到异常 schema
步骤3: 精确到表
└── 按 relation 查看 TOP10表
步骤4: 分析原因
├── Heap 类型多 → 大量 INSERT/UPDATE/DELETE
├── Btree 类型多 → 索引维护开销大
└── FPI 占比高 → checkpoint 过于频繁
步骤5: 采取措施
├── 限制异常租户写入速率
├── 暂停非核心批量任务
└── 优化索引策略

日常监控建议

建议定期执行以下查询,记录 WAL 产生趋势:
-- 每小时记录各数据库 WAL 产生量(可写入监控表)
INSERT INTO wal_monitor_log (check_time, database_name, wal_records, wal_bytes)
SELECT now(), database_name,
SUM(wal_records), SUM(wal_bytes + wal_fpi_bytes)
FROM tencentdb_wal_stat(10)
GROUP BY database_name;

wal_num 参数选择建议

场景
推荐 wal_num
说明
紧急排查
5 ~ 10
快速返回,查看最近的 WAL 来源
日常巡检
20 ~ 50
覆盖较长时间范围,数据更具代表性
深度分析
100 ~ 200
需要全面了解 WAL 分布时使用
说明:
wal_num 越大,分析时间越长。建议在业务低峰期执行大范围分析。

名词解释

名词
解释
WAL
Write-Ahead Logging,预写式日志。PostgreSQL 通过先写日志再写数据文件的方式来保证事务的持久性和崩溃恢复能力
LSN
Log Sequence Number,日志序列号。唯一标识 WAL 日志中的位置
RMGR
Resource Manager,资源管理器。WAL 按不同的操作类型分类,如 Heap(表数据)、Btree(B-tree 索引)、Transaction(事务)
FPI
Full Page Image,全页镜像。checkpoint 后首次修改某个数据页时,会将该页完整内容写入 WAL,用于崩溃恢复时避免部分写入问题
Replication Slot
复制槽。用于保留 WAL 日志直到下游订阅者消费完成。如果下游消费慢,会导致 WAL 无法被清理

注意事项

仅主库可用:在备库上执行会报错,这是因为备库没有独立的 WAL 写入。
权限要求:需要 pg_tencentdb_superuser 角色成员权限。
参数范围:wal_num 取值1 ~ 500,超出范围会报错。
名称解析:其他数据库中的对象名称可能显示为 <oid:N><filenode:N>,这是正常现象(跨库无法解析 catalog)。
性能影响:该函数读取 WAL 文件进行统计,wal_num 较大时执行时间会增加,建议避免在高峰期使用大 wal_num。
WAL 可用性:仅能分析尚未被清理的 WAL 文件,已回收的历史 WAL 无法分析。