Postgres WAL 背压:慢写入换不停库
后端约 5 分钟阅读

Postgres WAL 背压:慢写入换不停库

从 ClickHouse Managed Postgres 的 WAL backpressure 出发,讲清归档掉队、复制槽堆积与盘满 PANIC 的链路,以及观测指标和应用侧少帮倒忙的写法。

这两天 ClickHouse 工程博客在讲一件很“运维味”的事:Managed Postgres 里的 WAL backpressure。标题不性感,但比又一篇“Just use Postgres”有用——它回答的是:当 WAL 归档跟不上写入时,你是让磁盘写满后 PANIC,还是主动把笔速降下来。

Postgres 仍是 2026 年默认 OLTP。周边却在变:CDC 进数仓、AI 特征回写、多副本跨区、备份上对象存储。WAL 不再只是崩溃恢复的私房账本,而是整条数据管道的节拍器。节拍乱了,库先死,业务后知。

WAL 在忙什么

每笔提交前后,变更要进 Write-Ahead Log。崩溃恢复靠它;物理备份、流复制、逻辑解码(Debezium 那路)也靠它。磁盘上的 pg_wal 不是“可有可无的日志目录”,是生命线。

归档或 replica 一慢,WAL 段堆起来。盘满之后,Postgres 的选择很有限,严重时直接 PANIC 停库。很多事故复盘里,应用侧只看到“数据库连不上”,根因其实是:某个大事务、一次批量导入、或对象存储抖动,让 archiver 掉队太久。

ClickHouse 那篇文章的核心手段很直白:感知 WAL 积压,对客户端写入施加背压。短痛换长命——延迟升高、部分写入变慢或失败,但磁盘不被写穿,归档有时间追上。

背压听起来像“跟用户过不去”。比起半夜全站只读或直接挂掉,让一部分写请求早几分钟失败或变慢,通常是更体面的失败。关键路径可以走降级:排队、异步化、拒绝非核心写入,而不是假装无限磁盘存在。

背压比“加盘”老实

加盘能买时间,买不到纪律。没有背压时,流量高峰和归档故障叠在一起,盘再大也只是延迟爆炸。有背压时,系统把矛盾提前暴露成可观测的“写入变慢”,而不是半夜的不可用。

我在业务库上会盯这几类信号:

  • pg_stat_archiver:最后一次成功归档时间、失败次数。
  • WAL 目录体积与增长率;复制槽(replication slot)是否卡住老段。
  • 长事务与 idle in transaction:它们会挡住清理,间接堆 WAL。
  • 备份工具(WAL-G 等)的 lag 与重试。
  • checkpoint 与写放大:狂写时期盘 IO 是否被 WAL 和脏页回写一起打满。

告警别只设“磁盘 90%”。要设“归档延迟超过 N 分钟”“slot 落后超过 X GB”。那是背压该介入的窗口。N 和 X 没有宇宙常数,得按盘容量、峰值写入字节率和 RPO 目标算;算不清就先按“还能撑一次高峰”的保守值,再在演练里收紧。

图:写入、WAL、归档与副本之间的节拍

和 ClickHouse / CDC 管道的关系

很多团队已经是 Postgres 做事务,ClickHouse 做分析,中间走 CDC。这条链让 WAL 更忙:逻辑解码、发布订阅、槽位点,全都绑在同一条日志上。下游一堵,槽不前进,WAL 删不掉,上游盘先报警。

所以“统一数据栈”的运维问题,常常不是 SQL 怎么写,而是:

  1. 下游消费能否水平扩展,别让一个慢消费者钉死 slot。
  2. 大表初始同步是否与高峰写入错峰。
  3. 失败重放是否会制造写放大,反过来抽打主库。
  4. 要不要在网关或连接池做第二层限流,和数据库背压形成双闸门。
  5. 槽的保留策略是否会在消费者长时间离线后变成“隐形炸弹”。

我见过最冤的一次故障:分析侧周末扩容失败,槽位停了 14 小时,周一业务峰值一来,主库 WAL 盘先报警。业务同学以为是“促销把库打挂了”,其实是管道周末就埋了雷。

应用侧可以少帮倒忙

数据库背压是最后一道闸。应用还能少制造尖刺:

  • 批量导入用受控并发和可中断的作业,而不是一个开全表的超大事务。
  • 避免无意义的频繁单行提交刷屏;也避免相反的极端——单事务改几百万行。
  • 连接池设上限;把重试做成抖动退避,别在库已经喘时用风暴式重试补刀。
  • 只读分析尽量别打主库;要近实时,用副本或专用 CDC 出口。
  • 给非核心写入设计“可延迟”:点赞、埋点、推荐反馈可以进队列,别和订单提交抢同一条生命线。

如果你们已经在用托管 Postgres,问清楚供应商:WAL 积压时有没有自动限流、指标是否导出、slot 落后有没有独立告警。没有这些,等于你买了实例,却没买失败模式。

小结

“Just use Postgres”在 2026 年仍然成立,前提是你真的会用它的日志生命周期。WAL backpressure 不是新算法炫技,是承认物理世界:磁盘有限、网络会抖、下游会堵。与其在 PANIC 后复盘,不如在写入路径上留一扇会自动关小的阀。

下次做容量规划,别只问 QPS 和连接数。问一句:归档慢一小时,谁先痛,痛的是延迟还是停库。答案能决定你晚上能不能睡。

再补一句给排期用的话:先把归档延迟和 slot 落后做成 pager,再谈要不要上更花的多活。看不见节拍,谈架构只是换一种方式加班。

相关文章