PostgreSQL如何安全删除pg_wal目录内旧文件且不中断当前运行的数据库
PostgreSQL 无停机安全清理pg_wal目录方案
绝对不要手动直接删除pg_wal下的任意文件,误删会直接导致数据库损坏甚至无法启动,必须通过PostgreSQL自带的机制处理WAL清理
第一步:先排查pg_wal膨胀的常见原因
- 长期未执行基础备份,检查点无法标记旧WAL为可回收状态
- 已开启归档模式但归档命令执行失败,未完成归档的WAL会被永久保留
- 存在已废弃的流复制槽,主库会保留复制槽未接收的所有WAL文件
- wal_keep_size(PostgreSQL 13及以上版本)/ wal_keep_segments(13以下版本)参数配置过大,强制保留了超出业务需要的WAL
- 存在长时间未结束的运行事务,阻塞WAL回收机制运行
第二步:执行无停机清理操作
先尝试触发常规自动回收
执行以下SQL主动触发WAL切换和检查点,让数据库自动清理所有符合回收条件的旧WAL:
SELECT pg_switch_wal(); CHECKPOINT;
执行完成后查看pg_wal目录占用,如果已经下降则不需要额外操作。如果占用没有明显下降,对应下面的场景处理:
场景1:归档任务执行失败
- 查看归档运行状态:
SELECT * FROM pg_stat_archiver;
如果返回结果中last_failed_time晚于last_archived_time,说明归档链路异常,先修复归档路径权限、归档存储盘空间等问题,归档恢复正常后,已完成归档的旧WAL会自动被回收。
2. 如果业务不再需要归档,可以直接关闭归档触发回收:修改postgresql.conf配置文件中archive_mode = off,然后执行SELECT pg_reload_conf();重载配置即可生效,不需要重启数据库。
场景2:存在已废弃的流复制槽
- 查看所有复制槽状态:
SELECT slot_name, slot_type, active, restart_lsn FROM pg_replication_slots;
- 确认已经废弃的非活跃复制槽(
active字段为f且不再用于流同步),执行以下命令删除:
SELECT pg_drop_replication_slot('待删除的复制槽名称');
复制槽删除后,之前为该槽保留的未同步WAL会被自动回收。
场景3:WAL保留参数配置过大
- 查看当前保留配置:
- PostgreSQL 13及以上版本:
show wal_keep_size; - PostgreSQL 13以下版本:
show wal_keep_segments;
- 根据业务备份、流同步的实际需要调小参数,修改postgresql.conf后执行
SELECT pg_reload_conf();重载配置,超出保留阈值的旧WAL会自动被清理。
场景4:存在长时间运行的阻塞事务
- 查看运行超过1小时的活跃事务:
SELECT pid, datname, usename, now() - xact_start AS xact_duration, query FROM pg_stat_activity WHERE state != 'idle' AND xact_start < now() - interval '1 hour';
- 确认可以终止的无用长事务,执行命令结束:
SELECT pg_terminate_backend(对应事务的pid);
事务结束后WAL回收机制会自动运行。
注意事项
所有清理操作全程不需要重启数据库,不会影响现有业务运行。
如果需要将WAL归档到外置存储释放本地空间,只要保证归档命令配置正常,PostgreSQL会在归档成功后自动清理本地旧WAL,不需要手动干预。
内容的提问来源于stack exchange,提问作者bryan
相关产品推荐
相关产品推荐

