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

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

实验现象

  1. Patroni完成基础备份启动PG后,集群进入Patroni leader/running状态
  2. 执行以下命令应用备集群配置:
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"
  1. 多数场景下会触发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完整性:
    pg_waldump pg_wal/00000001000000930000004C | head -20
    
    若报错则文件损坏,需从主库重新获取该WAL文件

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 08:43:12