postgrresql 搭建简单流复制主从

主库配置:

创建复制用户:登录主库数据库,创建一个专门用于复制的用户(如果还未创建)。

sql
CREATE USER replica WITH REPLICATION ENCRYPTED PASSWORD 'replica';

修改 pg_hba.conf:编辑主库的数据目录下的 pg_hba.conf 文件,允许备库(偶数机)使用复制用户连接。在文件中添加如下行(假设偶数机IP为 192.168.1.102):

host    replication   replica             192.168.81.0/24         trust

方式 1:仅允许 192.168.81.129 这个 IP 的复制连接(推荐)
# 格式:host    replication    用户名    客户端IP/掩码    认证方式
host    replication     postgres     192.168.81.129/32    md5  # 或 trust(测试环境)

方式 2:允许整个 192.168.81.0/24 网段的复制连接(适合集群环境)
host    replication     postgres     192.168.81.0/24      md5

/usr/local/pg12/bin/pg_ctl -D /usr/local/pg12/data reload


修改 postgresql.conf:修改主库的 postgresql.conf 文件,开启必要的复制参数。
listen_addresses = '*'          # 监听所有地址,或指定偶数机IP
wal_level = replica              # 设置为 replica 或更高,以支持流复制
max_wal_senders = 10             # 最大 WAL 发送进程数,至少为1
wal_keep_size = 1GB              # (或 wal_keep_segments)保留的 WAL 日志大小,防止备库落后太多
hot_standby=on


重启主库服务:使配置生效。
/usr/local/pg12/bin/pg_ctl -D /usr/local/pg12/data stop
/usr/local/pg12/bin/pg_ctl -D /usr/local/pg12/data start

从库配置

停止备库服务并清空数据目录:确保备库服务停止,并清空其数据目录($PGDATA),以便从主库拉取基础备份。
/usr/local/pg12/bin/pg_ctl -D /usr/local/pg12/data stop
rm -rf /usr/local/pg12/data/*   # 请替换为你的实际数据目录路径 */

从主库拉取基础备份:使用 pg_basebackup 工具从主库复制整个数据集群到备库
pg_basebackup -h 192.168.1.101 -U replica -p 5432 -D /var/lib/pgsql/16/data -Fp -Xs -P -R

-D: 备库本地数据目录
-Xs: 使用流复制模式备份最新WAL
-R: 关键参数,会在备份后自动创建 standby.signal 文件,并将主库连接信息写入 postgresql.auto.conf,告知备库如何连接主库 。
eg:primary_conninfo = 'user=replica host=192.168.81.128 port=1536 sslmode=disable sslcompression=1'

启动备库:启动备库服务,它将成为基数机的异步流复制备库。
/usr/local/pg12/bin/pg_ctl -D /usr/local/pg12/data start

验证异步同步状态

postgres=# SELECT client_addr, state, sync_state FROM pg_stat_replication;
  client_addr   |   state   | sync_state 
----------------+-----------+------------
 192.168.81.129 | streaming | async
你应该能看到偶数机的IP地址,且 sync_state 列显示为 async,表示异步复制正常运行 。

创建新数据库 newdb1 并验证:
-- 在主库执行
CREATE DATABASE newdb1;

如果一切正常,你应该能在备库的数据库列表中看到刚刚在主库创建的 newdb1。这表明数据已通过流复制成功同步 

主从切换:

此步骤模拟主库故障或计划内维护,我们将偶数机提升为新的主库。

执行切换

将原基数机(旧主库)降级为备库:

优雅关闭旧主库:
# 在旧主库(基数机)执行,使用 fast 模式快速关闭
pg_ctl -D /var/lib/pgsql/16/data stop -m fast
# 或 systemctl stop postgresql


将原偶数机(旧备库)提升为新主库:
# 在新主库(偶数机)执行提升命令

/usr/local/pg12/bin/pg_ctl -D /usr/local/pg12/data promote

# 或 systemctl promote postgresql@16-main (取决于系统)
# 或创建一个触发器文件 (如果配置了 promote_trigger_file)

SELECT client_addr, state, sync_state FROM pg_stat_replication;

重新配置复制方向(可选但推荐,以便新主库有备库)

同步时间线
注意要使用用户postgres,否者会报错执行读取二进制文件权限不足
pg_rewind --target-pgdata=/usr/local/pg12/data/ --source-server="user=postgres password=postgres host=192.168.81.12 port=1536"
为了让新的主库(原偶数机)拥有一个新的备库(原基数机),我们需要在旧主库上重新配置,使其指向新主库。

在旧主库(基数机):
确保其数据目录是干净的或重新拉取基础备份(如果数据不重要,可直接复用现有数据,但需确保与新主库一致)。

编辑或确认 postgresql.auto.conf 文件(或在 postgresql.conf 中)包含指向新主库的连接信息
vim postgresql.auto.conf
primary_conninfo = 'host=192.168.1.102 port=5432 user=replica password=your_strong_password application_name=standby1'

primary_conninfo = 'user=replica host=192.168.81.129 port=1536 sslmode=disable sslcompression=1'
在数据目录中创建 standby.signal 文件,告诉 PostgreSQL 以备库模式启动。(空目录)
touch /usr/local/pg12/data/standby.signal

启动旧主库服务,它现在会作为新主库(偶数机)的备库开始运行。
/usr/local/pg12/bin/pg_ctl -D /usr/local/pg12/data start

验证新主库上的操作是否同步

在新的主库(原偶数机)创建数据库 newdb2:
-- 在新的主库(偶数机)执行
CREATE DATABASE newdb2;

pg_stat_replication 表的状态说明

状态总览与速查

状态 含义 阶段/场景 期望状态
startup WAL发送进程正在启动,尝试与备库建立连接 连接初始化阶段 短暂过渡
catchup 备库已连接,但数据落后于主库,正在“追赶”以同步数据 数据同步追赶阶段 短暂过渡
streaming 正常同步状态。备库已与主库同步,正持续接收WAL日志流 稳态流复制 ✅ 正常
backup 主库正在通过 pg_basebackup 等工具执行在线基础备份 在线备份阶段 正常(备份时)
stopping WAL发送进程正在正常关闭,通常意味着复制连接即将断开 连接关闭阶段 短暂过渡

状态流转路径解析

在典型的流复制场景中,状态会沿着清晰的路径变化:

  • 流复制启动:startup → catchup → streaming。备库重启或初始建立连接时会经过这些阶段,快速追平数据后进入 streaming 稳态。
  • 执行在线备份 (pg_basebackup):startup → backup → streaming → stopping。备份开始时进入 backup 状态,为保持一致性可能短暂切换到 streaming,完成后进入 stopping。
  • 备库数据落后:当已处于 streaming 状态的备库因网络或负载等原因落后主库时,会切回 catchup 状态追赶数据,追平后再自动恢复为 streaming。

state 字段描述了WAL发送进程的状态,而 sync_state 字段则标识了同步方式(异步 async、同步 sync、潜在 potential 等),两者共同描述了一个完整的复制连接状态。

posted @ 2026-05-18 13:55  数据库小白(专注)  阅读(17)  评论(0)    收藏  举报