PostgreSQL 中 pg_wal 目录里的 .ready .done .history 文件的生命周期

说明: 本文基于GPT回答生成


文章目录

PostgreSQL 中 pg_wal 目录里的 .ready / .done / .history 分别是干什么的?

你这个问题非常偏运维,而且和归档(archive_mode)强相关,正好也很容易被误删。

下面我按你关心的几个点,一次讲清楚:

  • 是干啥的
  • 一般多大
  • 里面内容长什么样
  • 什么时候产生
  • 什么时候自动删除
  • 什么时候会残留
  • 什么时候可以手工删

先给你一张总览表(后面逐个展开):

文件类型 所在目录 作用
00000001000000000000005A.ready pg_wal/archive_status 表示:这个 WAL 等待归档
00000001000000000000005A.done pg_wal/archive_status 表示:这个 WAL 已归档
00000002.history pg_wal 时间线历史文件

注意:

👉 .ready / .done 不在 pg_wal 目录本身

👉 在:

复制代码
pg_wal/archive_status/

下面正式拆开讲。


一、xxx.ready 是干什么的?

位置

复制代码
$PGDATA/pg_wal/archive_status/

例如:

复制代码
00000001000000000000005A.ready

作用一句话说明

这个 WAL 段文件,已经写完了,正在等待 archive_command 去归档。


什么时候产生?

当:

  • 你开启了
conf 复制代码
archive_mode = on

并且:

  • 某一个 WAL 段文件切换完成时

PostgreSQL 会:

  1. 在 pg_wal 里生成 WAL 文件

  2. 同时在

    pg_wal/archive_status

里生成一个同名的:

复制代码
.ready

文件


举例

生成的 WAL 文件:

复制代码
pg_wal/00000001000000000000005A

对应就会有:

复制代码
pg_wal/archive_status/00000001000000000000005A.ready

这个文件里内容是啥?

👉 基本是空文件

一般是 0 字节。

你可以理解为:

只是一个标志文件


一般大小是多少?

通常:

复制代码
0 字节

什么时候会变成 done?

当你的:

conf 复制代码
archive_command

返回 0(成功)后:

PostgreSQL 会:

  • 删除 .ready

  • 创建:

    .done



二、xxx.done 是干什么的?

位置

同样在:

复制代码
pg_wal/archive_status/

例如:

复制代码
00000001000000000000005A.done

作用一句话说明

这个 WAL 文件已经被成功归档过了。


什么时候产生?

当:

复制代码
archive_command 执行成功

PostgreSQL 就会创建:

复制代码
.done

里面内容是啥?

👉 也是空文件

一般是 0 字节。


一般大小?

同样:

复制代码
0 字节

.done 什么时候删除?

注意这个点:

👉 PostgreSQL 并不会马上删 .done

.done 的清理由内部机制处理,通常是在:

  • WAL 文件被回收/删除之后
  • 或者 checkpoint 相关流程中

最终会被清掉。



三、.ready 和 .done 的完整生命周期

最典型流程是:

复制代码
WAL 切换完成
   ↓
生成 xxx.ready
   ↓
archive_command 成功
   ↓
删除 xxx.ready
生成 xxx.done
   ↓
后续回收时清理 xxx.done


四、xxx.history 是干什么的?

这个完全是另一类文件。


位置

直接在:

复制代码
pg_wal/

比如:

复制代码
00000002.history

作用一句话说明

记录时间线(timeline)切换历史,用于恢复和主备切换。


什么时候产生?

只有在发生:

👉 时间线切换

才会生成。

典型场景:

  • 从备库提升为主库(promote)
  • 做时间点恢复(PITR)
  • restore_command 恢复到新的 timeline

举例

比如你原来 timeline 是:

复制代码
00000001

提升备库后:

新 timeline 变成:

复制代码
00000002

那么就会生成:

复制代码
00000002.history

这个文件里面内容一般长什么样?

内容是文本。

类似这样:

复制代码
1    0/16B6C50    no recovery target specified

格式大概是:

复制代码
父时间线ID    切换LSN    说明

一般多大?

非常小。

一般:

  • 几十字节
  • 几百字节


五、什么时候会自动删除?

1️⃣ xxx.ready

👉 正常情况下:

  • archive_command 成功后
  • 立刻被删掉

2️⃣ xxx.done

👉 会在 WAL 回收时被清理

但这个不是强实时的。


3️⃣ xxx.history

👉 默认不会自动删除。

这是设计行为。



六、什么时候会残留?

这个问题在生产中非常常见。


(一)大量 .ready 残留

最常见原因只有一个:

👉 archive_command 一直失败

比如:

结果是:

复制代码
.ready 一直存在
.done 不生成

你会看到:

复制代码
pg_wal/archive_status/
  xxxx.ready
  yyyy.ready
  zzzz.ready

不断堆积。



(二).done 很多

这种一般不是故障。

只是:

  • WAL 还没被回收
  • 或 checkpoint 周期还没触发到清理点


(三).history 文件残留

这是正常现象。

只要发生过:

  • promote
  • PITR
  • 时间线切换

就会留下 history 文件。



七、什么时候可以手动删除?

这个非常重要,我给你直接分结论。


❌ 千万不要手工删除 .ready

原因很简单:

你删了:

复制代码
xxx.ready

PostgreSQL 就认为:

👉 这个 WAL 不需要归档了

而实际上:

👉 归档可能还没成功

会直接破坏归档链。



⚠️ 一般也不建议手工删除 .done

除非:

你非常明确:

  • 这个实例不再使用归档
  • 或你要重建环境


⚠️ history 文件能不能删?

结论:

👉 不建议删

特别是以下场景:

  • 你有:

    • 归档
    • 备库
    • PITR 需求

history 是恢复链的重要组成部分。



八、什么时候是"可以安全清理"的场景?

只有在以下场景中,才可以考虑手工清理这些文件:


场景 1:这个库已经不做归档、不做恢复

比如:

  • archive_mode 已关闭
  • 不存在备库
  • 不会再做 PITR
  • 是一个纯单机实例

那么:

.done.history 对你基本没有意义。


但即便如此:

👉 正确做法也不是手工删文件

而是:

  • 让 PostgreSQL 自己管理
  • 或重建集群


九、和你当前运维场景最相关的一个风险点

你前面一直在做:

  • 巡检
  • 清理
  • 自动化脚本

我非常明确地提醒你一句:

👉 不要把:

复制代码
pg_wal/archive_status

加入任何自动清理脚本。

尤其不要写:

bash 复制代码
find pg_wal -name "*.ready" -delete

这是非常危险的。



十、你可以用来巡检的一条非常实用的 SQL

你可以用这个来判断归档是否堆积:

sql 复制代码
select
  count(*) filter (where status = 'ready') as ready_cnt,
  count(*) filter (where status = 'done')  as done_cnt
from pg_stat_archiver;

不过更推荐的是:

sql 复制代码
select *
from pg_stat_archiver;

你重点看:

  • last_failed_wal
  • last_failed_time
  • failed_count


十一、结合你的环境,我给你一个非常实用的判断建议

你现在的场景是:

  • 单机 PostgreSQL
  • 以稳定运维为主
  • 很多自动巡检脚本

我建议你加一个规则:

如果:

复制代码
archive_mode = on

并且:

复制代码
pg_wal/archive_status/*.ready 数量 > 0
并持续增长

基本可以直接报警:

👉 归档通道已经异常。



十二、最后给你一版"DBA速记版总结"

ready

👉 等待归档

👉 0 字节

👉 archive_command 成功前存在

👉 失败会大量堆积

👉 不能删


done

👉 已完成归档

👉 0 字节

👉 后续会被清理

👉 不建议人工干预


history

👉 时间线切换历史

👉 文本文件

👉 非常小

👉 用于恢复链

👉 不建议删除

相关推荐
全栈老石18 分钟前
拆解低代码引擎核心:元数据驱动的"万能表"架构
数据库·低代码
倔强的石头_19 小时前
kingbase备份与恢复实战(二)—— sys_dump库级逻辑备份与恢复(Windows详细步骤)
数据库
jiayou642 天前
KingbaseES 实战:深度解析数据库对象访问权限管理
数据库
李广坤3 天前
MySQL 大表字段变更实践(改名 + 改类型 + 改长度)
数据库
爱可生开源社区4 天前
2026 年,优秀的 DBA 需要具备哪些素质?
数据库·人工智能·dba
随逸1774 天前
《从零搭建NestJS项目》
数据库·typescript
加号35 天前
windows系统下mysql多源数据库同步部署
数据库·windows·mysql
シ風箏5 天前
MySQL【部署 04】Docker部署 MySQL8.0.32 版本(网盘镜像及启动命令分享)
数据库·mysql·docker
李慕婉学姐5 天前
Springboot智慧社区系统设计与开发6n99s526(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
数据库·spring boot·后端
百锦再5 天前
Django实现接口token检测的实现方案
数据库·python·django·sqlite·flask·fastapi·pip