在一次 PostgreSQL 性能排查中,我遇到了这样一段日志:
checkpoints are occurring too frequently (29 seconds apart)
HINT: Consider increasing the configuration parameter "max_wal_size".
而另一边,在 PolarDB 文档/实践中却看到:
checkpoint 频率约 30 秒一次
看起来很矛盾:
-
PostgreSQL:30 秒一次是"异常,需要优化"
-
PolarDB:30 秒一次是"设计行为"
那么问题来了:
checkpoint 到底应该频繁还是稀疏?
研究一番后,我得出了这样的结论,这篇文章从原理到架构,带你彻底搞清楚。
一、什么是 Checkpoint?
Checkpoint 本质是:
将内存中的脏页刷回磁盘,并记录一个一致性恢复点
在 PostgreSQL 中,checkpoint 的作用包括:
-
限制 WAL 回放长度
-
控制恢复时间
-
保证数据持久性
二、两种完全不同的 checkpoint 策略
1️⃣ PostgreSQL 传统策略:低频 checkpoint
典型参数:
max_wal_size = 8GB~16GB
checkpoint_timeout = 15min
checkpoint_completion_target = 0.9
特点:
-
checkpoint 间隔长
-
每次写盘量大
-
WAL 累积多
2️⃣ PolarDB / 云原生策略:高频 checkpoint
特点:
-
checkpoint 间隔短(如 30s)
-
每次写盘量小
-
持久化推进更频繁
三、为什么 PostgreSQL 不喜欢高频 checkpoint?
来看一个真实现象:
checkpoint 每 29 秒触发一次
每次写 ~800MB ~1GB 数据
问题:
1. 写放大严重
频繁 checkpoint 会导致:
-
同一页被多次刷盘
-
IO 压力持续升高
2. WAL 增长更快
checkpoint 后:
-
第一次修改页面 → full page write
-
checkpoint 越频繁 → WAL 越多
3. 吞吐下降
表现为:
-
TPS 抖动
-
写延迟升高
四、为什么 PolarDB 反而选择高频 checkpoint?
关键点:架构不同
1️⃣ PostgreSQL 架构(本地存储)
Shared Buffers → 本地磁盘
↑
WAL
特点:
-
数据页在本地
-
checkpoint = 真正的磁盘写入
-
IO 成本高
2️⃣ PolarDB 架构(计算存储分离)
Compute Node → Shared Storage
↓
WAL/日志驱动
特点:
-
存储层分离
-
WAL/日志更核心
-
数据页刷写机制不同
关键区别
| 项目 | PostgreSQL | PolarDB |
|---|---|---|
| 存储 | 本地 | 共享存储 |
| checkpoint成本 | 高 | 相对可控 |
| WAL作用 | 辅助恢复 | 核心同步机制 |
| 优化目标 | 吞吐优先 | 恢复/一致性优先 |
五、两种策略本质对比
方案 A:低频 checkpoint(PostgreSQL)
优点
-
写入吞吐高
-
IO 更集中
-
减少写放大
缺点
-
WAL 较多
-
崩溃恢复时间更长
方案 B:高频 checkpoint(PolarDB)
优点
-
恢复更快
-
RTO 更可控
-
数据推进更平滑
缺点
-
写入开销更分散
-
对传统架构不友好
六、核心差异:吞吐 vs 恢复
可以用一句话总结:
PostgreSQL:追求吞吐
PolarDB:追求恢复能力
七、如何判断你的数据库该用哪种策略?
适合 PostgreSQL 低频 checkpoint 的场景
-
高并发写入(OLTP)
-
批量写入
-
本地 SSD/NVMe
-
单机或传统主备
建议:
max_wal_size = 8GB~16GB
checkpoint_timeout = 15min
适合高频 checkpoint 的场景
-
云原生数据库
-
分离式存储
-
高可用优先
-
对恢复时间敏感
八、一个真实调优案例
问题:
checkpoint 每 29 秒触发
Execution latency 波动明显
参数:
max_wal_size = 2GB
checkpoint_timeout = 5min
优化:
max_wal_size = 8GB
checkpoint_timeout = 15min
结果:
-
checkpoint 间隔从 29s → 数分钟
-
IO 平滑
-
写入稳定
九、一个关键认知误区
很多人看到:
PolarDB checkpoint 30s
就以为:
PostgreSQL 也应该这样调
这是错误的。
正确认知
架构不同 → 最优参数完全不同
十、总结
PostgreSQL
少 checkpoint,大 checkpoint
→ 提升吞吐
PolarDB
多 checkpoint,小 checkpoint
→ 提升恢复能力
最后一条建议
如果你在标准 PostgreSQL 中看到:
checkpoints are occurring too frequently
不要犹豫:
先调大 max_wal_size
一句话总结
checkpoint 不是越频繁越好,也不是越少越好,而是要匹配数据库架构。