如何手动将PostgreSQL WAL文件应用至其他数据库集群
实现方案
该需求完全可行,基于PostgreSQL原生的PITR(时间点恢复)机制即可实现,无需配置持续同步的流复制备节点,所有操作可手动执行。
前置配置要求
- 确认A库WAL配置满足重放要求:修改A库
postgresql.conf参数后重启生效:wal_level = replica(默认配置通常满足要求,不可设为minimal,否则WAL缺少必要重放信息)archive_mode = onarchive_command = 'test ! -f /自定义WAL归档存储路径/%f && cp %p /自定义WAL归档存储路径/%f',该配置会把A库生成的完整WAL段自动落盘到独立归档目录,避免WAL被循环覆盖。
- 准备干净的B端基础数据:你之前拷贝过A的data目录到B且启动过的实例已经无法用于后续WAL重放——实例启动写入后会生成本地WAL记录,和A库的WAL链LSN偏移完全断裂,必须重新从A库拷贝一份一致性基础备份到B:拷贝前在A库执行
select pg_start_backup('incr_sync');,全量拷贝data_directory到B后,再在A库执行select pg_stop_backup();,拷贝到B的数据目录不要启动、不要做任何写入修改,权限保持为postgres运行用户所有。
定期同步操作步骤
每次需要将A的增量数据同步到B时,按以下流程操作:
- 如果B库处于运行状态,先执行停库命令:
pg_ctl stop -D /B节点数据目录路径 -m fast,确认无残留postgres进程。 - 从A库的WAL归档目录,拷贝上次同步后新生成的所有完整WAL段文件,放到B节点数据目录下的
pg_wal子目录中,保持原文件名、权限正确。 - 在B节点数据目录下创建空的标记文件
recovery.signal(适用于PostgreSQL 12及以上版本;11及更早版本需配置recovery.conf,写入restore_command = 'cp %p %f'即可)。如果不需要重放到指定时间点/事务ID,无需额外配置恢复参数,默认会重放pg_wal目录下所有可用WAL;如果不想重放完成后自动切换为读写模式,可以在postgresql.conf中添加recovery_target_action = 'shutdown',重放完成后实例会自动关机,保留恢复状态,下次同步直接追加新WAL即可,无需重新全量拷贝基础备份。 - 启动B节点实例:
pg_ctl start -D /B节点数据目录路径,实例会自动进入恢复模式重放所有拷贝过来的A库WAL,重放完成后会自动删除recovery.signal标记,进入正常可用状态,此时B库数据和A库对应WAL截止位置的数据完全一致。
常见问题避坑
- 不要从A库正在运行使用的
pg_wal目录直接拷贝未归档的WAL文件,这类文件可能还处于写入状态、内容不完整,会导致重放中断,必须从配置好的归档目录取已经归档完成的完整WAL段。 - 如果重放过程中提示WAL缺失、校验失败,只需要把对应缺失/损坏的WAL文件补全到B的
pg_wal目录,重启实例即可继续重放。 - 如果每次重放完成后B库切换到了读写模式,下次同步前必须重新全量拷贝A的最新一致性基础备份到B,否则会因为WAL链不匹配无法重放。
内容的提问来源于stack exchange,提问作者Kyosh
相关产品推荐
相关产品推荐

