Postgres热备启动停滞:WAL文件存在仍等待contrecord
问题背景
我们基于PostgreSQL 16,使用复制槽测试Patroni多数据中心高可用方案,搭建远程集群的核心流程是主库有写入操作时执行基础备份,通过Patroni实现复制槽热备。
主集群配置示例:
postgresql: parameters: archive_command: /bin/true archive_mode: 'on' checkpoint_completion_target: '0.9' checkpoint_timeout: 300 default_statistics_target: 100 effective_cache_size: 12GB effective_io_concurrency: 2 fsync: 'on' full_page_writes: 'on' hot_standby: true hot_standby_feedback: true idle_in_transaction_session_timeout: 10min log_min_duration_statement: 10000 log_min_error_statement: ERROR log_min_messages: WARNING log_temp_files: 4000 maintenance_work_mem: 3GB max_connections: 512 max_parallel_maintenance_workers: 4 max_parallel_workers: 10 max_parallel_workers_per_gather: 2 max_prepared_transactions: 1024 max_replication_slots: 10 max_slot_wal_keep_size: 20GB max_wal_senders: 10 max_wal_size: 2GB max_worker_processes: 10 min_wal_size: 512MB random_page_cost: 2 shared_buffers: 8GB synchronous_commit: remote_write track_functions: all track_io_timing: 'on' wal_buffers: 16MB wal_compression: 'on' wal_keep_segments: 128 wal_level: replica work_mem: 16MB use_pg_rewind: true use_slots: true retry_timeout: 14
实验现象
- Patroni完成基础备份启动PG后,集群进入
Patroni leader/running状态 - 执行以下命令应用备集群配置:
curl -X PATCH http://localhost:8008/config \ -H "Content-Type: application/json" \ -d '{ "standby_cluster": { "host": "standby.example.com", "port": 5432, "primary_slot_name": "standby_slot" } }' \ --data-urlencode "force=true"
- 多数场景下会触发pg_rewind,之后集群进入
Standby leader/streaming状态;但偶尔rewind结束后,集群停留在Standby leader/starting状态
PG日志关键信息:
2024-08-19 20:02:00 UTC:::@:[762363]:LOG: contrecord is requested by 93/4C000028 2024-08-19 20:02:00 UTC:::@:[762363]:LOG: waiting for WAL to become available at 93/4C000040
排查结果
- 等待的LSN记录生成于基础备份之后,主库已归档该记录
- 备集群
pg_wal目录存在对应LSN的WAL文件,但数据库卡在启动阶段,无法进入流复制状态 - 复制槽当前未处于活跃状态
疑问:为何主库上存在对应WAL文件,却未发送给热备以使其进入流复制状态?
可能原因及解决方法
1. 复制槽未正确激活
pg_rewind完成后,Patroni需重新建立流复制连接并激活复制槽,若备库recovery配置未正确关联复制槽,或连接建立时出现异常,主库复制槽会处于非活跃状态,不会主动推送WAL:
- 检查备库
postgresql.auto.conf(PostgreSQL 12+),确认primary_slot_name已设为standby_slot,且primary_conninfo包含正确的主库地址、认证信息 - 在主库执行
SELECT pg_replication_slot_advance('standby_slot', '93/4C000040');(替换为目标LSN),强制推进复制槽LSN,随后重启备库Patroni服务
2. 备库WAL文件无法被读取
备库pg_wal目录存在目标WAL文件,但可能存在权限问题或文件损坏:
- 检查
pg_wal目录及文件属主为postgres,目录权限0700、文件权限0600 - 用
pg_waldump验证WAL完整性:
若报错则文件损坏,需从主库重新获取该WAL文件pg_waldump pg_wal/00000001000000930000004C | head -20
3. Patroni状态切换逻辑异常
执行PATCH配置并加force=true时,Patroni可能未完成从leader到standby的状态切换,导致启动流程卡住:
- 查看备库Patroni日志,确认是否存在状态切换失败、主库连接超时等错误
- 停止备库Patroni服务,清理
pg_wal/pg_replslot目录下的无效槽信息,重新启动Patroni以重建流复制连接
4. 主库WAL归档配置无效
主库archive_command: /bin/true未实际归档WAL,虽max_slot_wal_keep_size=20GB会保留复制槽所需WAL,但如果目标WAL段已从主库pg_wal目录移除,将无法推送:
- 修正归档配置为有效命令(如归档至外部存储),或关闭
archive_mode避免混淆 - 在主库执行
SELECT pg_ls_dir('pg_wal');,确认目标WAL文件是否存在;若不存在,需从备份恢复该文件至备库pg_wal目录
5. pg_rewind后LSN对齐偏差
pg_rewind完成后,备库LSN可能未完全对齐主库当前LSN,导致备库请求的WAL段未被复制槽跟踪:
- 若备库能进入只读模式,执行
SELECT pg_current_wal_lsn();确认当前LSN与日志中等待的LSN是否一致 - 建议在主库低峰期执行基础备份,避免备份过程中大量WAL生成导致LSN偏差过大
内容的提问来源于stack exchange,提问作者Ganesh
相关产品推荐
相关产品推荐

