原文地址 https://hdombrovskaya.wordpress.com/2025/09/27/how-i-learned-to-use-wal_inspect/
自从上次我写博客讨论任何现实生活中的问题和调查以来,已经有一段时间了。这是我非常高兴的一个,因为它花了一段时间,而且并不明显,但我找到了问题的根本原因!
这个问题已经持续了几个月:其中一个 Postgres 数据库 WAL 文件系统正在以惊人的速度增长,比数据库本身快很多倍。并不是说我们不能立即删除 WAL,但这种情况使任何数据库恢复都成为一场真正的噩梦。起初,我怀疑回填算法欠佳的长交易。确实,有很多工作定期运行,可以改进,但是,我注意到了几件事。
首先,当用户修复一个主要嫌疑人作业时,WAL 增长的情况没有改变。其次,增长速度不能用这些次优作业来解释:它们删除和重新加载的数据量仍然比我们正在处理的 WAL 大小小。最后,我决定做我从一开始就应该做的事情——看看这些超快速增长的 WAL 到底是什么。
这是我所做的:
注意: 需要pg的版本是15或者以上
-- 需要先切换到对应的数据库里去安装扩展
create extension pg_walinspect;
select pg_current_wal_insert_lsn();
记下这里的值,假设是 '17797/A167C8E8'
select pg_current_wal_insert_lsn()
记下这里的值,假设是 '17797/FEDE0CC8'
-- 使用pg_get_wal_stats函数检查下这段LSN内的WAL记录
select * from pg_get_wal_stats('17797/A167C8E8', '17797/FEDE0CC8', true); 
令我惊讶的是,我意识到 97% 的 WAL 都存储了有关锁的信息!老实说,我甚至不知道锁记录在 WAL 文件中,所以我感谢 Postgres 社区的慷慨启发!
现在我知道该去哪里看,我运行了以下内容:
select * from pg_get_wal_records_info('17797/A167C8E8', '17797/FEDE0CC8')
where
resource_manager='Heap'
and record_type='LOCK';
放大如下:

接下来,我找到了包含所有这些锁的表:
select * from pg_class where oid =10229951;
或
SELECT
c.oid,
current_database() AS database_name,
n.nspname AS schema_name,
c.relname AS table_name,
c.relkind
FROM
pg_class c
JOIN
pg_namespace n ON c.relnamespace = n.oid
WHERE
-- c.relkind = 'r' -- 只查询普通表
-- AND n.nspname NOT LIKE 'pg_%'
-- AND n.nspname != 'information_schema'
c.oid =10229951
ORDER BY
n.nspname,
c.relname;当我找到 table_name 时,我能够检查 pgBadger 数据库(或者其它审计日志类平台),我找到了具体的语句,类似如下:
select * from this_customer_logs.this_database_log_t_2025_07_25
where query like '%this_table_name%';事实证明,虽然 UPDATE 似乎是缓慢/锁定等待的原因,但当没有等待时,UPDATE 本身会在 1 到 2 毫秒之间执行。缓慢的实际原因是读取事务中执行的一次缓a慢选择 - 请参阅事件序列:

因此,这种巨大的 WAL 增长的原因是一个(实际上是两个)缓慢的 SELECT 语句!谁能猜到?!
本文系外文翻译,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文系外文翻译,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。