本文主要记录 PostgreSQL 流复制(Streaming Replication)主从热备的配置步骤:主库参数与复制用户/复制槽、备库 pg_basebackupstandby.signal、复制状态验证,以及手动 promote。文末补充 sslmode、WAL 保留参数与常见报错处理。

本方案不包含自动故障切换。主库故障时需人工 pg_ctl promote / pg_promote(),并改应用连接。若需要自动切换,应另外部署 Patroni、repmgr 等方案。大版本以 16 为例,路径与 unit 名按发行版调整;密码与 IP 使用占位符。

背景说明

角色职责
Primary(主库)读写;产生 WAL 并发送给备库
Standby(备库)接收并应用 WAL;hot_standby=on 时可只读查询
复制槽主库保留备库尚未消费的 WAL,比单纯 wal_keep_size 更可靠
手动切换确认旧主不可用后提升备库,避免脑裂

环境信息

项目取值(示例 / 占位)
PostgreSQL16.x(主备主版本一致
主库<primary-host>,端口 5432
备库<standby-host>
数据目录<pgdata>(如 /var/lib/postgresql/16/main
复制用户replication_user
复制槽<slot_name>(如 standby1_slot
服务名postgresql-16 或发行版等价 unit

前置:主备网络互通;防火墙放行 5432;备库数据目录可被 pg_basebackup 写入(空目录或不存在)。

配置主库

postgresql.conf

wal_level = replica
max_wal_senders = 5
# 使用复制槽时可不依赖 wal_keep_size;见下文 WAL 参数说明
# wal_keep_size = 512MB
hot_standby_feedback = on

wal_level 等参数通常需重启生效。

pg_hba.conf

允许备库以 replication 身份连接(地址与认证方式按现场收紧):

# TYPE  DATABASE     USER               ADDRESS           METHOD
host    replication  replication_user   <standby-ip>/32   scram-sha-256

创建复制用户与复制槽

CREATE USER replication_user WITH REPLICATION PASSWORD '<password>';
SELECT pg_create_physical_replication_slot('<slot_name>');

使配置生效

# systemd 示例
systemctl restart postgresql-16
# 或
pg_ctl restart -D <pgdata>

仅改 pg_hba 时有时可 reload;涉及 wal_level 仍应重启。

准备与配置备库

停止服务并清空数据目录

备库不得带着另一套 initdb 出来的集群去“接”主库。数据目录须为空或不存在,再由 pg_basebackup 填充。

systemctl stop postgresql-16
# 确认后清理目标目录内容(破坏性,先备份自有配置)
# rm -rf <pgdata>/*

pg_basebackup

备库上执行(版本与主库主版本一致):

pg_basebackup \
  -h <primary-host> -p 5432 \
  -U replication_user \
  -D <pgdata> \
  -Fp -Xs -P \
  -S <slot_name> \
  --wal-method=stream

按提示输入复制用户密码。PG12+ 不再依赖 recovery.conf-R 行为因版本而异,本文采用手动写 standby.signal + primary_conninfo

standby.signal 与 postgresql.conf

touch <pgdata>/standby.signal

在备库 postgresql.conf(或 conf.d 覆盖)中:

primary_conninfo = 'host=<primary-host> port=5432 user=replication_user password=<password> sslmode=prefer application_name=standby1'
primary_slot_name = '<slot_name>'
hot_standby = on

主库未开 SSL 时,sslmode=prefer 会回退明文;也可显式 disable。生产建议规划证书后使用 require / verify-full

只读访问还需配置备库 pg_hba.conf

启动备库

systemctl start postgresql-16
# 查看日志,期望进入 standby 并开始 streaming

日志中常见关键字示意(非固定原文):

entering standby mode
started streaming WAL from primary

验证复制状态

主库

SELECT * FROM pg_stat_replication;

关注:state 是否为 streamingsent_lsn / write_lsn / flush_lsn / replay_lsn 是否接近;application_name 是否与 primary_conninfo 一致;异步复制时 sync_state 多为 async

备库

SELECT pg_is_in_recovery();          -- 期望 t
SELECT * FROM pg_stat_wal_receiver;  -- status 期望 streaming

数据抽检

在主库写入测试表/行,稍后在备库只读查询是否可见。备库禁止写操作。

手动故障切换

  1. 确认旧主库已故障且不会双写(必要时隔离网络)。
  2. 在备库提升:
pg_ctl promote -D <pgdata>
# 或 SQL:SELECT pg_promote();
  1. 修改应用连接指向新主库。
  2. 旧主恢复后一般需清空数据,按上文重新 pg_basebackup 做成新备库,或废弃。

无自动切换:不会自动改写 VIP/DNS,应用层与运维流程需提前演练。

sslmode 说明

primary_conninfosslmode 控制备库连主库时的 TLS 行为(主库未开 SSL 时):

主库无 SSL 时
disable明文,成功
allow / prefer(默认倾向)尝试后回退明文,通常成功
require / verify-ca / verify-full失败(无法建立 SSL)

主库开启 SSL 且证书配齐后,生产更推荐 verify-full

WAL 保留:wal_keep_size 与 max_slot_wal_keep_size

示例:

wal_keep_size = 0
max_slot_wal_keep_size = -1

含义概括:

  • wal_keep_size = 0:不按固定尺寸额外囤积 WAL,主要交给复制槽等机制。
  • max_slot_wal_keep_size = -1:不限制单槽可滞留的 WAL 体积上限。

结果是:强依赖复制槽保证备库可追;若槽对应备库长期离线且未删槽,pg_wal 可能撑满磁盘。必须监控磁盘与 pg_replication_slotsactive、滞后 LSN)。更稳妥时可给 max_slot_wal_keep_size 设合理上限并配合告警。

常见问题

database system identifier differs between the primary and standby

备库数据目录不是当前主库的 pg_basebackup 产物(本地 initdb、旧集群、指错主库等)。处理:停备库 → 清空 <pgdata> → 重新 basebackup → 写 standby.signalprimary_conninfo → 启动。

pg_basebackup: incompatible server version

备库上的 pg_basebackup 与主库主版本不一致。检查:

pg_basebackup --version
psql --version

安装与主库同主版本的 server/client,或用完整路径调用(如 /usr/lib/postgresql/16/bin/pg_basebackup),并调整 PATH。报错后工具可能清理未完成目录,属保护性行为。

备库宕机、主库仍正常

  • 主库读写一般不受影响。
  • 使用复制槽时主库会为离线备库保留 WAL,磁盘有涨满风险
  • 备库只读流量中断。
  • 备库恢复后:槽与 WAL 仍在则可继续追;若未用槽且 WAL 已丢,需重新 basebackup。

注意事项

  • 复制密码写在 primary_conninfo 时注意文件权限;可用 .pgpass 等减少明文落盘(按环境选择)。
  • 有备库不等于免备份;仍需定期物理/逻辑备份。
  • 切换前必须防止旧主复活双写。
  • 本文不替代官方发行说明;参数名以当前大版本文档为准。

参考资料