PostgreSQL流复制主备切换分Failover和Switchover:前者在主库宕机时紧急提升备库,需确认replay_delay在秒级内并执行pg_promote;后者为计划内互换,要求主备在线、停止写入后双向配置再提升;原主库重入须用pg_rewind避免冲突;切换后须验证可写性、复制连接及应用连接地址。

PostgreSQL流复制主备切换,核心是把备库提升为主库,并让原主库(恢复后)重新以备库身份加入集群。它分两种场景:计划内主动切换(Switchover)和故障应急切换(Failover),操作逻辑不同,风险点也不同。
一、Failover:主库已宕机,紧急提升备库
这是最常见也最需谨慎的操作。目标是快速恢复写服务,但必须确认备库数据足够新,避免丢数据。
- 先检查备库是否已同步到最新状态:
SELECT pg_is_in_recovery(), pg_last_wal_receive_lsn(), pg_last_wal_replay_lsn(), now() - pg_last_xact_replay_timestamp() AS replay_delay;
若 pg_is_in_recovery() 返回 t,且 replay_delay 在秒级内,说明可安全提升。 - 执行提升命令:
sudo -u postgres pg_ctl promote -D /var/lib/pgsql/data
或直接在备库运行 SQL:
SELECT pg_promote(); - 提升后,备库立即退出恢复模式,变成可读写的新主库,standby.signal 文件自动被删除,日志中会出现 "database system is ready to accept connections" 和 "promoted to primary" 记录。
二、Switchover:计划内主备角色互换
适用于维护、升级或负载均衡调整。要求主备都在线,且能通信,整个过程可控。
- 先停止原主库写入(如暂停应用或设为只读),并确认所有 WAL 已被备库接收并回放完毕。
- 在原主库上创建 standby.signal 文件,并配置 primary_conninfo 指向新主库(即原备库):
echo "primary_conninfo = 'host=192.168.1.11 port=5432 user=replicator password=xxx'" >> $PGDATA/postgresql.auto.conf - 在原备库执行 pg_ctl promote,使其成为新主库。
- 启动原主库(此时已是备库角色),它会自动连接新主库开始同步。
三、原主库重入集群:用 pg_rewind 避免全量重建
Failover 后,原主库若想重新当备库,不能直接启动——它可能有未同步的写入,会导致数据冲突。PG 9.5+ 推荐用 pg_rewind 快速对齐:
- 确保新主库已开启 wal_log_hints = on 且 max_replication_slots ≥ 1(最好提前配好)。
- 停掉原主库服务,然后在新主库上查出切换时刻的 LSN:
SELECT pg_switch_wal(); -- 或查 pg_controldata 输出中的 Latest checkpoint location - 在原主库机器上执行:
sudo -u postgres pg_rewind --source-server="host=192.168.1.11 port=5432 dbname=postgres user=replicator" -D /var/lib/pgsql/data - 重写完成后,按备库方式配置 standby.signal 和 primary_conninfo,再启动即可。
四、切换后必须验证的三件事
- 新主库是否可写:执行 INSERT INTO test VALUES (now()); 看是否成功;
- 连接是否已切走:查 pg_stat_replication,应看到旧主库(如果已重入)作为客户端连上来;
- 应用是否连对地址:如果没配 VIP 或 DNS 切换,务必更新应用的数据源配置,指向新主库 IP 和端口。

















