PostgreSQL 12如何缩小pg_wal目录体积?升级后wal过大求助
首先得明确:修改max_wal_size只是设置了WAL自动清理的上限,但它不会立刻删除已经堆积的WAL文件,得先排除阻止WAL清理的因素,再触发清理流程。下面是你需要检查和调整的关键点:
1. 检查WAL归档是否正常
如果你的archive_mode是开启状态,但归档命令执行失败(比如归档存储满了、权限问题),PostgreSQL会一直保留WAL文件,直到归档成功。这是最常见的WAL堆积原因。
- 用下面的SQL查看归档状态:
SELECT * FROM pg_stat_archiver;
重点看failed_count字段,如果数值大于0,说明归档有失败记录,得先修复归档问题(比如清理归档存储、修正archive_command的路径/权限)。
- 如果暂时不需要归档,可以临时关闭归档(需要重启PostgreSQL):
修改postgresql.conf:
然后重启服务,之后WAL清理就能正常进行了。archive_mode = off
2. 排查长时间运行的事务
长事务(尤其是idle in transaction状态的)会阻止WAL被清理,因为PostgreSQL需要保留这些WAL来支持事务回滚或备库的同步。
- 查找长事务:
SELECT pid, now() - xact_start AS duration, query FROM pg_stat_activity WHERE state = 'idle in transaction' ORDER BY duration DESC;
如果发现运行时间很长的事务,直接用SELECT pg_terminate_backend(pid);杀掉对应的进程,之后WAL清理就会逐步推进。
3. 检查未使用的复制槽
如果之前配置了流复制,但是备库已经下线或停止同步,主库上的复制槽会一直保留WAL文件,直到备库重新连接或复制槽被删除。
- 查看复制槽状态:
SELECT slot_name, slot_type, active, pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn) AS retained_wal_size FROM pg_replication_slots;
如果有active = false的复制槽,且确认不再需要,直接删除:
SELECT pg_drop_replication_slot('你的复制槽名称');
4. 手动触发WAL清理
在解决上面的问题后,你可以手动触发WAL切换和检查点,让PostgreSQL立刻清理符合条件的旧WAL:
-- 切换到新的WAL文件 SELECT pg_switch_wal(); -- 触发检查点,让系统检查WAL使用情况并清理 SELECT pg_checkpoint();
执行完这些操作后,pg_wal目录的体积应该会逐渐降到max_wal_size(4GB)附近。
补充说明
升级后WAL堆积的额外原因:PostgreSQL 12在升级过程中可能会执行一些后台操作(比如自动重建索引、更新统计信息),这些操作会生成大量WAL。如果同时遇到上面的某个阻止清理的因素,就会导致WAL快速堆积到61GB的规模。
内容的提问来源于stack exchange,提问作者ajlind

