PostgreSQL主库启动触发自动恢复的原因及规避方案咨询
问题描述
我在Ubuntu 16.04环境中运行PostgreSQL 9.5,架构部署如下:
PostgreSQL主库(9.5版本,Ubuntu 16.04,Docker容器)--rsync-->Walstore备份服务器(Docker容器)--rsync-->PostgreSQL备库(9.5版本,Ubuntu 16.04,Docker容器)。
当主库崩溃时,我们会将备库数据(与主库数据同步,仅缺少recovery.conf文件)复制到主库数据目录,随后重启主库服务器。但主库启动后触发了自动恢复,相关日志如下:
postgresql-docker-primary-1 | * Starting PostgreSQL 9.5 database server postgresql-docker-primary-1 | ...done. postgresql-docker-primary-1 | 2022-11-28 10:14:59 UTC [27-1] LOG: database system was shut down in recovery at 2022-11-28 10:11:14 UTC postgresql-docker-primary-1 | 2022-11-28 10:14:59 UTC [27-2] LOG: database system was not properly shut down; automatic recovery in progress postgresql-docker-primary-1 | 2022-11-28 10:14:59 UTC [27-3] LOG: redo starts at 0/1700DB8 postgresql-docker-primary-1 | 2022-11-28 10:14:59 UTC [27-4] LOG: invalid record length at 0/3000060 postgresql-docker-primary-1 | 2022-11-28 10:14:59 UTC [27-5] LOG: redo done at 0/3000028 postgresql-docker-primary-1 | 2022-11-28 10:14:59 UTC [27-6] LOG: last completed transaction was at log time 2022-11-28 10:04:37.388433+00 postgresql-docker-primary-1 | 2022-11-28 10:14:59 UTC [27-7] LOG: MultiXact member wraparound protections are now enabled postgresql-docker-primary-1 | 2022-11-28 10:14:59 UTC [26-1] LOG: database system is ready to accept connections postgresql-docker-primary-1 | 2022-11-28 10:14:59 UTC [31-1] LOG: autovacuum launcher started postgresql-docker-primary-1 | 2022-11-28 10:14:59 UTC [34-1] [unknown]@[unknown] LOG: incomplete startup packet
由于备库数据与主库同步,我预期主库启动不会触发自动恢复,想了解PostgreSQL判断是否触发恢复的机制。在生产环境中,该自动恢复耗时约3小时,会导致服务长时间不可用,希望能规避此情况,同时寻求相关文档指引。
答案
一、PostgreSQL触发自动恢复的判断机制
PostgreSQL启动时会依据数据目录内的关键文件和状态标记,判断是否需要进入恢复流程:
- pg_control控制文件:这个文件记录了数据库全局状态,包括上次关闭状态、检查点信息、WAL位置等。备库通常持续运行在恢复模式下,其pg_control会标记为「处于恢复中」;即便你没复制recovery.conf,这个状态标记会被同步到主库数据目录,启动时PostgreSQL会识别并触发恢复。另外,如果数据库是异常关闭(崩溃、强制终止),pg_control也会标记为「未正常关闭」,同样会触发恢复。
- WAL日志完整性:启动时会检查WAL日志尾部是否为完整记录。如果rsync复制时恰好赶上备库写入WAL,可能导致复制的WAL文件不完整,PostgreSQL会通过redo修复到最近的完整事务点,这也会触发恢复流程。
从你的日志能直接印证:database system was shut down in recovery at 2022-11-28 10:11:14 UTC,说明复制过来的备库数据本身是在恢复状态下关闭的,所以主库启动时会继续执行恢复。
二、规避长时间自动恢复的方法
确保备库数据处于「干净关闭」状态再复制
- 复制前先执行快速关闭备库:
pg_ctl stop -m fast。快速关闭会触发检查点,更新pg_control为正常关闭状态,同时确保WAL日志完整性。这样复制到主库后,启动时不会触发自动恢复。 - 若备库不能停机,可先在备库执行
pg_start_backup(),完成rsync后再执行pg_stop_backup()。这个操作会生成一致性备份标签,PostgreSQL启动时会识别为合法备份集,避免不必要的redo操作。
- 复制前先执行快速关闭备库:
用PostgreSQL原生工具替代rsync
- 使用
pg_basebackup创建备库基础备份,它会自动处理备份一致性,生成的备份集启动时恢复效率更高,避免rsync可能带来的WAL不完整问题。 - 主库崩溃后,直接将备库提升为主库(
pg_ctl promote),再重新搭建新备库。这个原生故障切换流程比复制备库数据回原主库更高效,完全规避恢复耗时问题。
- 使用
调整WAL参数减少恢复时长
- 增大
wal_buffers和checkpoint_segments(PostgreSQL 9.5参数,10+版本改为max_wal_size),降低检查点频率,减少恢复时需要redo的WAL日志量,从而缩短恢复时间。
- 增大
三、相关文档指引
PostgreSQL 9.5官方文档的以下章节可深入了解:
- 备份与恢复:详细讲解备份机制、一致性备份方法及恢复流程原理。
- 服务器启动与关闭:解释启动时恢复判断逻辑及恢复过程细节。
- 流复制:针对主备架构的部署和故障转移,提供原生可靠的故障切换方案。
内容的提问来源于stack exchange,提问作者ctn
相关产品推荐
相关产品推荐

