💡 核心原理:Full Page Write (FPW) 是 PostgreSQL 在检查点后首次修改数据页时,将整个页面(8KB)完整写入 WAL 的机制,核心是解决部分写(partial write) 导致的磁盘页面损坏问题,确保崩溃恢复的可靠性。
一、 问题根源:部分写(Partial Write)的威胁
数据页物理结构
PostgreSQL 数据页 (8KB)
┌──────────────────────────────┐
│ Page Header │
├──────────────┬───────────────┤
│ Block 1 │ Block 2 │ ← 操作系统写入单元 (通常 4KB)
├──────────────┼───────────────┤
│ Block 3 │ Block 4 │
└──────────────┴───────────────┘
部分写灾难场景
二、 FPW 的救赎机制
FPW 工作流程
崩溃恢复过程
步骤 | 操作描述 | 磁盘页面状态 | WAL 内容 | 结果状态 |
---|---|---|---|---|
1 | 检查点完成 | [A A A A] (完好) | - | - |
2 | 修改页面触发FPW | 崩溃! [B B A A] | FPI: [A A A A] WAL-Mod1 |
损坏状态 |
3 | 恢复:应用FPI | [A A A A] (恢复) | 已使用 | 基础恢复 |
4 | 恢复:重放WAL修改 | [B B B B] | 已使用 | 最终正确状态 |
三、 FPW 的双面性:安全 vs 性能
安全价值分析
保护机制 | 解决的问题 | 重要性级别 |
---|---|---|
防止部分写 | 页面撕裂 | 关键 |
确保恢复基础 | WAL重放可靠性 | 必需 |
避免永久损坏 | 数据完整性 | 核心 |
性能代价对比(修改1000个页面)
大概的空间占用示例
场景 | WAL大小 | 放大倍数 | I/O压力 |
---|---|---|---|
无FPW | ~100KB | 1x | 低 |
有FPW | ~8.1MB | 81x | 高 |
四、 决策流程图:是否关闭FPW?
总结
FPW 本质:在非原子写硬件上,用空间换安全的保险机制
一些建议:
- 🛡️ 永不关闭FPW 除非满足所有硬件条件
- ⚙️ PostgreSQL 16+建议开启
wal_compression
和wal_init_zero
- 📊 每月监控检查点前后的WAL生成峰值
最后说一句:当DBA考虑关闭生产系统的FPW时,应在你的存储工程师能书面保证8KB原子写,并愿意用职业生涯担保,发誓永不跑路时,才是考虑关闭FPW的时机。