You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PostgreSQL主备复制如何减少WAL文件生成量及优化存储

问题背景

在PostgreSQL主备复制架构中,选定1台备节点作为WAL归档节点,每2小时使用tar命令压缩该备节点上的已归档WAL文件,但存储占用始终居高不下。存储30天、90天周期备份时存在严重存储容量压力,数据恢复过程中下载、重放WAL文件的耗时也很长。

初始已生效配置参数:

wal_level=replica
wal_compression=on
archive_mode = always

初始未启用的注释参数:

archive_timeout
checkpoint_timeout

核心观测现象:通过pg_waldump检测发现WAL内容中70%90%为全页镜像(FPI),在备节点调整参数后仍观测到每分钟生成34个WAL文件,调整后的备节点参数如下:

name        | setting | unit
--------------------+---------+------
 archive_timeout    | 0       | s
 checkpoint_timeout | 3600    | s
 checkpoint_warning | 3600    | s
 max_wal_size       | 4000    | MB
 min_wal_size       | 2000    | MB
 shared_buffers     | 458752  | 8kB
 wal_buffers        | 4096    | 8kB
 wal_compression    | on      |
 wal_level          | replica |

pg_waldump统计示例显示FPI占比达87%:

pg_waldump --stats 0000000100000498000000B2
Type                                           N      (%)          Record size      (%)             FPI size      (%)        Combined size      (%)
----                                           -      ---          -----------      ---             --------      ---        -------------      ---
XLOG                                           1 (  0.00)                  114 (  0.01)                    0 (  0.00)                  114 (  0.00)
Transaction                                 3070 ( 10.35)               104380 (  4.86)                    0 (  0.00)               104380 (  0.63)
Storage                                        0 (  0.00)                    0 (  0.00)                    0 (  0.00)                    0 (  0.00)
CLOG                                           0 (  0.00)                    0 (  0.00)                    0 (  0.00)                    0 (  0.00)
Database                                       0 (  0.00)                    0 (  0.00)                    0 (  0.00)                    0 (  0.00)
Tablespace                                     0 (  0.00)                    0 (  0.00)                    0 (  0.00)                    0 (  0.00)
MultiXact                                      0 (  0.00)                    0 (  0.00)                    0 (  0.00)                    0 (  0.00)
RelMap                                         0 (  0.00)                    0 (  0.00)                    0 (  0.00)                    0 (  0.00)
Standby                                        2 (  0.01)                  100 (  0.00)                    0 (  0.00)                  100 (  0.00)
Heap2                                        590 (  1.99)                33863 (  1.58)                46192 (  0.32)                80055 (  0.48)
Heap                                        6679 ( 22.51)               578232 ( 26.92)              4482508 ( 30.92)              5060740 ( 30.41)
Btree                                      19330 ( 65.14)              1430918 ( 66.62)              9967524 ( 68.76)             11398442 ( 68.48)
Hash                                           0 (  0.00)                    0 (  0.00)                    0 (  0.00)                    0 (  0.00)
Gin                                            0 (  0.00)                    0 (  0.00)                    0 (  0.00)                    0 (  0.00)
Gist                                           0 (  0.00)                    0 (  0.00)                    0 (  0.00)                    0 (  0.00)
Sequence                                       0 (  0.00)                    0 (  0.00)                    0 (  0.00)                    0 (  0.00)
SPGist                                         0 (  0.00)                    0 (  0.00)                    0 (  0.00)                    0 (  0.00)
BRIN                                           0 (  0.00)                    0 (  0.00)                    0 (  0.00)                    0 (  0.00)
CommitTs                                       4 (  0.01)                  120 (  0.01)                    0 (  0.00)                  120 (  0.00)
ReplicationOrigin                              0 (  0.00)                    0 (  0.00)                    0 (  0.00)                    0 (  0.00)
Generic                                        0 (  0.00)                    0 (  0.00)                    0 (  0.00)                    0 (  0.00)
LogicalMessage                                 0 (  0.00)                    0 (  0.00)                    0 (  0.00)                    0 (  0.00)
                                        --------                      --------                      --------                      --------
Total                                      29676                       2147727 [12.90%]             14496224 [87.10%]             16643951 [100%]

开启log_checkpoints=on后获取的检查点日志如下:

2022-06-15 07:08:57 UTC [11] LOG:  checkpoint starting: time
2022-06-15 07:29:57 UTC [11] LOG:  checkpoint complete: wrote 67010 buffers (14.6%); 0 WAL file(s) added, 12 removed, 56 recycled; write=1259.767 s, sync=0.010 s, total=1259.961 s; sync files=253, longest=0.003 s, average=0.001 s; distance=1125728 kB, estimate=2176006 kB
2022-06-15 07:38:57 UTC [11] LOG:  checkpoint starting: time
2022-06-15 07:59:57 UTC [11] LOG:  checkpoint complete: wrote 61886 buffers (13.5%); 0 WAL file(s) added, 20 removed, 10 recycled; write=1259.740 s, sync=0.005 s, total=1259.878 s; sync files=185, longest=0.002 s, average=0.001 s; distance=491822 kB, estimate=2007588 kB

待解答核心疑问:

  • 是否有可行方案减少WAL文件生成量,或易落地的WAL管理方式?
  • 仅在备节点修改WAL相关参数是否生效?备节点归档的WAL是主节点发送的原始文件,还是根据备节点自身配置重新生成的?
  • 备节点改参数后仍每分钟生成3~4个WAL,是否需要在主节点修改对应参数?主节点配置是否会影响备节点的WAL生成行为?

核心解答

主备WAL生成逻辑说明

  • 流复制架构下,备节点接收、归档的WAL完全是主节点生成后通过流复制协议传输的原始WAL流,备节点不会重新生成WAL内容,checkpoint_timeout、wal_compression、max_wal_size这类控制WAL生成规则的参数在备节点修改对归档WAL无任何效果,所有控制WAL生成量的参数必须在主节点调整才会生效。
  • 仅备节点本地恢复触发的检查点、热备反馈产生的少量本地WAL(不会进入归档流程)受备节点参数影响,归档链路的WAL内容、生成速度完全由主节点决定。

WAL高占用、FPI占比过高的根因

FPI(全页镜像)是PostgreSQL的页损坏防护机制:每次检查点之后第一次修改某数据页时,会将整个数据页完整内容写入WAL。你当前环境FPI占比接近9成,核心原因是检查点触发过于频繁——检查点间隔越短,检查点后需要重复写入全页镜像的页数量越多,WAL膨胀越严重。
从提供的检查点日志可以看出,主节点实际检查点间隔仅30分钟,远未达到备节点配置的3600秒,说明主节点要么checkpoint_timeout设置过短,要么max_wal_size阈值太小,WAL量触达阈值后提前触发了检查点。

可落地的WAL减容与管理方案

  • 第一优先级:调整主节点参数
    • 将主节点checkpoint_timeout设置为18003600秒(3060分钟,不建议低于30分钟),max_wal_size设置为日常峰值半小时WAL生成量的4~6倍(参考日志中半小时生成约1.1GB WAL的情况,可设为8GB16GB),避免WAL量触顶提前触发检查点,该调整可直接减少30%60%的FPI写入。
    • 确认主节点wal_compression=on(备节点开启该参数无压缩效果,主节点开启后会对WAL中的FPI做压缩,实测可将WAL整体体积压缩至原体积的30%~50%)。
    • 保持主节点archive_timeout=0,不要设置为几十秒的小值,该参数会强制超时切换WAL段,设置过小会产生大量仅写入几KB的无效WAL文件,额外占用存储。
  • 第二优先级:优化归档存储策略
    • 替换每2小时打tar包的逻辑,直接在archive_command中使用高压缩率算法实时压缩WAL,优先选择zstd -19等级压缩,相同压缩率下速度是gzip的35倍,压缩率比gzip高20%30%,既省空间也能避免未压缩WAL临时堆积占满磁盘。
    • 做WAL分层存储:30天内需要用于快速恢复的WAL存在高速块存储,30~90天的冷备WAL转存至低成本归档存储,无需长期占用高性能存储容量。
  • 第三优先级:生命周期与进阶优化
    • 结合基础备份周期清理过期WAL:无需保留超过「最近2个全量基础备份生成时间+最长恢复窗口」的WAL,比如每周做1次全量基础备份,仅需保留最近2周的WAL即可满足全量恢复需求,更早的WAL可直接删除,无需硬存90天。
    • 若业务可接受极端情况下丢失1个检查点周期的数据,且底层存储有可靠的页校验、快照能力,可开启full_page_writes=off,能直接砍掉80%以上的WAL体积;该参数存在宕机后数据页损坏的风险,无可靠存储保障不建议开启。

常见避坑点

  • 不要在备节点调整WAL生成类参数做无用功,所有影响归档WAL的配置均以主节点为准。
  • 不要为了“加快检查点速度”将max_wal_size设置过小,过小的阈值会导致检查点频繁触发,FPI写入量暴增,WAL总占用反而会升高,恢复时WAL重放时间也会更长。
  • 不要存储原始未压缩WAL,实时压缩的空间收益远高于定期打包压缩,还能降低磁盘被打满的风险。

内容的提问来源于stack exchange,提问作者Anto

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 10:24:13