说明: 本文基于GPT回答生成
文章目录
- [PostgreSQL 中 pg_wal 目录里的 `.ready` / `.done` / `.history` 分别是干什么的?](#PostgreSQL 中 pg_wal 目录里的
.ready/.done/.history分别是干什么的?) -
- [一、xxx.ready 是干什么的?](#一、xxx.ready 是干什么的?)
- [二、xxx.done 是干什么的?](#二、xxx.done 是干什么的?)
- [三、.ready 和 .done 的完整生命周期](#三、.ready 和 .done 的完整生命周期)
- [四、xxx.history 是干什么的?](#四、xxx.history 是干什么的?)
- 五、什么时候会自动删除?
-
- [1️⃣ xxx.ready](#1️⃣ xxx.ready)
- [2️⃣ xxx.done](#2️⃣ xxx.done)
- [3️⃣ xxx.history](#3️⃣ xxx.history)
- 六、什么时候会残留?
-
- [(一)大量 .ready 残留](#(一)大量 .ready 残留)
- 你会看到:
- [(二).done 很多](#(二).done 很多)
- [(三).history 文件残留](#(三).history 文件残留)
- 七、什么时候可以手动删除?
-
- [❌ 千万不要手工删除 `.ready`](#❌ 千万不要手工删除
.ready) - [⚠️ 一般也不建议手工删除 `.done`](#⚠️ 一般也不建议手工删除
.done) - [⚠️ history 文件能不能删?](#⚠️ history 文件能不能删?)
- [❌ 千万不要手工删除 `.ready`](#❌ 千万不要手工删除
- 八、什么时候是"可以安全清理"的场景?
-
- [场景 1:这个库已经不做归档、不做恢复](#场景 1:这个库已经不做归档、不做恢复)
- 九、和你当前运维场景最相关的一个风险点
- [十、你可以用来巡检的一条非常实用的 SQL](#十、你可以用来巡检的一条非常实用的 SQL)
- 十一、结合你的环境,我给你一个非常实用的判断建议
- 十二、最后给你一版"DBA速记版总结"
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 会:
-
在 pg_wal 里生成 WAL 文件
-
同时在
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 一直失败
比如:
- 远程服务器不可达
- 目录权限错误
- 脚本报错
- 网络问题: 比如 PostgreSQL 12.4数据库"孤儿"归档问题处理的经验总结
结果是:
.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
👉 时间线切换历史
👉 文本文件
👉 非常小
👉 用于恢复链
👉 不建议删除