在PostgreSQL的流复制架构里,热备库的作用不只是分担读流量,更是主库故障后的最后一道防线。热备库通过重放主库传输过来的WAL日志保持数据接近实时同步,但它的默认状态是只读的,任何写入请求都会返回错误。当主库因为硬件故障、网络中断或计划维护需要下架时,热备库必须脱离恢复状态,变成能够处理读写请求的新主库。这个动作在PostgreSQL中称为promote,中文常叫提升或激活。执行promote后,备库会停止WAL重放,切换到一个新的时间线,并允许客户端建立写入连接。

一、理解热备库的恢复模式与promote的前提条件
PostgreSQL热备库在正常工作期间处于恢复模式,也就是说它的主要进程会不断从主库接收WAL日志并应用,同时对外提供只读查询。可以通过在备库上执行 SELECT pg_is_in_recovery(); 来确认当前状态,返回结果为true表示仍然处于恢复中,返回false则表示已经提升为主库。这个状态是判断备库角色的重要依据。
执行promote之前需要满足几个前提条件。第一,主库必须已经停止写入或者与备库之间的网络已经隔离,否则可能出现两个节点同时接受写入的脑裂问题。第二,备库需要保证已经接收到足够多的WAL日志,特别是使用同步复制时,要确认所有已提交事务都已经落盘。第三,检查数据目录的权限和磁盘空间,确保提升过程中PostgreSQL能够写入控制文件和新时间线信息。第四,如果使用高可用管理工具,如Patroni或repmgr,需要按照工具推荐的方式执行切换,而不是手动直接promote。
promote的内部动作并不复杂,但影响很大。它会生成一个新的时间线ID,将当前WAL位置标记为恢复结束点,写入控制文件,并删除备库标识文件。完成这些操作后,数据库才正式接受写入。如果这些步骤中任何一步失败,可能导致数据库无法启动或者数据不一致。
二、使用pg_ctl promote命令激活热备库
PostgreSQL 12及以后的版本推荐使用 pg_ctl promote 命令来激活热备库。这个命令不需要连接数据库,直接在备库服务器上以操作系统用户身份执行即可,因为它是通过控制文件与后台进程通信完成的。基本语法如下:
# 在备库所在服务器上执行 pg_ctl promote -D /var/lib/postgresql/14/main -W -t 60
其中 -D 参数指定数据目录,-W 表示等待提升操作完成,-t 指定最长等待秒数。执行成功后会在终端看到类似 server promoted 的输出,同时备库的日志中会记录时间线切换信息。建议在执行时加上超时参数,避免命令无限期挂起。
提升过程中数据库可能会短暂中断已经存在的只读连接,这是正常现象。如果客户端仍然连接在备库上,需要重新连接才能执行写入。对于关键业务,可以在低峰期执行切换,或者在应用层做好连接重试逻辑。另外,如果在提升过程中发现错误,不要反复快速执行命令,应该先查看数据库日志,确认失败原因后再操作。
三、通过触发文件方式执行promote
在PostgreSQL 12之前的版本中,很多DBA习惯使用触发文件来激活热备库。具体做法是在备库的 recovery.conf 文件中配置 trigger_file 参数,当这个文件被创建时,PostgreSQL会自动结束恢复并提升为主库。示例配置如下:
# recovery.conf 片段 standby_mode = 'on' trigger_file = '/tmp/postgresql.trigger'
然后只需要在操作系统上执行 touch /tmp/postgresql.trigger 创建这个空文件,备库就会感知到并开始提升。这种方式的好处是可以通过脚本或其他监控系统方便地触发切换,但它的缺点也很明显:一旦误创建触发文件,备库就会被意外提升,恢复起来比较麻烦。
从PostgreSQL 12开始,recovery.conf 被移除,恢复参数并入主配置文件或 postgresql.auto.conf,同时 trigger_file 参数也被废弃。官方更推荐使用 pg_ctl promote,因为它有更明确的返回状态和错误提示,也便于自动化工具集成。不过在某些旧版本环境中,触发文件方式仍然在广泛使用。
四、promote后的验证与主备切换的后续处理
执行promote之后,第一件事就是验证新主库是否正常工作。连接数据库并执行 SELECT pg_is_in_recovery();,如果返回false说明已经成功脱离恢复状态。还可以使用 pg_controldata 查看控制文件中的数据库状态,正常应该显示为 in production 而不是 in archive recovery。时间线ID也会在控制文件中显示,新主库的时间线通常比原主库大1。
验证完成后,还需要处理原主库的善后工作。如果原主库只是计划内维护,恢复后不能直接启动为读写模式,否则会和新主库形成双主。正确的做法是使用 pg_rewind 工具把原主库回退到分叉点,然后作为新备库重新加入复制。如果原主库数据损坏严重,最保险的方法是直接使用 pg_basebackup 从新主库重新构建备库。
最后要调整应用连接和访问入口。检查连接字符串、连接池配置以及VIP漂移,确保所有写流量都指向新主库,读流量可以分摊到其他备库。同时更新监控系统中的主从角色标记,避免后续自动化运维误判。
五、promote常见故障与避坑指南
最常见的问题是数据不一致。如果备库的WAL接收位置 pg_last_wal_receive_lsn() 和重放位置 pg_last_wal_replay_lsn() 之间存在较大差距,说明还有部分日志没有应用完。此时如果强行promote,这部分未应用的已提交事务就会丢失。切换前务必确认这两个值相等或差距极小,并且主库已经停止写入。
另一个典型问题是脑裂。当网络分区发生时,主库可能仍然存活,但备库因为联系不上主库而执行了promote。此时两个节点都会接受写入,数据冲突几乎不可避免。要避免这种情况,需要在架构上引入隔离机制,例如使用STONITH设备强制关闭旧主库,或者由高可用管理工具统一决策。手动操作时一定要先确认主库真正不可用,而不是仅仅网络抖动。
时间线分叉也是一个容易踩的坑。promote之后新主库进入新的时间线,旧主库如果保留着旧时间线的WAL,直接和新主库建立复制关系会失败,报错通常包含 timeline 相关字样。解决方法是使用 pg_rewind 将旧主库恢复到分叉点之前,或者重建备库。因此切换前要规划好回退方案,保留足够的WAL归档,否则可能陷入无法恢复的境地。
PostgreSQL热备库promote命令修改时间:2026-10-06 21:53:34