PostgreSQL 16 流复制主从搭建实战:从踩坑到明白

环境:Ubuntu 22.04 × 2 · PostgreSQL 16 · 适合生产参考

上个月给项目搭主从,照着老教程一路配下来"看起来都对了",结果主库跑两天后 WAL 把磁盘撑爆,主库直接罢工。排查完才明白是复制没配防漂移,WAL 只进不出。这篇把一次配稳的完整流程和坑都写出来,你可以直接抄。

先说架构:一主一从,异步流复制(生产最常用),主库 192.168.1.10,从库 192.168.1.11,都是 PG 16。

一、主库配置:三个参数一个用户

编辑主库的 postgresql.conf:

ini 复制代码
listen_addresses = '*'
wal_level = replica              # 流复制最低要求,默认就是它,确认一下
max_wal_senders = 10            # wal 发送进程上限,留点余量
max_replication_slots = 10      # 复制槽上限,后面要用

建专用复制用户(别拿超级用户跑复制):

sql 复制代码
CREATE ROLE repl WITH REPLICATION LOGIN PASSWORD 'ReplPass_2026';

二、pg_hba.conf 放行复制连接

sql 复制代码
# TYPE   DATABASE   USER   ADDRESS          METHOD
host    replication repl   192.168.1.0/24   scram-sha-256

注意这行的 DATABASE 是 replication ,不是业务库名。它匹配的是复制流的专用通道,和业务连接的 host all all ... 是两回事。改完 reload 即可:SELECT pg_reload_conf();(但 listen_addresses 是 postmaster 级参数,第一次改要 restart)。

三、从库:pg_basebackup 一把梭

从库装同版本 PG 16 后,先停服务,用 pg_basebackup 从主库拉基线:

css 复制代码
sudo systemctl stop postgresql

sudo -i -u postgres

pg_basebackup -h 192.168.1.10 -U repl -D /var/lib/postgresql/16/main \
  -Fp -Xs -P -R --slot=standby1 --create-slot

参数说人话:

  • -Fp:纯文件格式,和普通数据目录一样
  • -Xs:备份期间 WAL 以流的方式同步过来,不依赖主库留旧日志
  • -R:自动生成 standby.signal 并写好 primary_conninfo,省手写
  • --slot=standby1 --create-slot:创建并绑定复制槽,防 WAL 被提前清理的关键,下面细说

确认属主后启动:

bash 复制代码
exit
sudo systemctl start postgresql

四、验证:两条命令定乾坤

主库上看发送状态:

sql 复制代码
SELECT client_addr, state, sync_state, write_lag, flush_lag, replay_lag
FROM pg_stat_replication;

看到 state = streaming 就成了。replay_lag 是从库回放延迟,平时盯着它就知道主从落后多少。

从库上确认身份:

csharp 复制代码
SELECT pg_is_in_recovery();   -- true,说明是从库,只读

顺手验证只读 :在从库执行 CREATE TABLE t1(id int);,报 cannot execute CREATE TABLE in a read-only transaction 就是正常的------从库天生只读,别想着手工改。

五、我踩的坑,帮你提前踩了

坑1:不配复制槽,WAL 漂移撑爆主库

不用复制槽时,主库按 wal_keep_size 留 WAL。从库断线超过保留窗口后重连,只能从头再来一次 basebackup。我一开始按老教程只设了 wal_keep_size,从库断了一天,重搭。用复制槽后,主库会替从库保留未消费的 WAL,从库断了多久都能续上 ------这就是上面 --slot 的意义。但注意反向风险,见坑2。

坑2:复制槽是把双刃剑------从库长期下线,WAL 堆积照样爆盘

我那次爆盘的真正原因:复制槽 standby1 在,但从库所在机器被回收了没人管,主库一直替它留 WAL,留到磁盘 100%。所以生产上复制槽必须配监控 :盯 pg_replication_slots 的 active 和 restart_lsn,从库确认不要了就 SELECT pg_drop_replication_slot('standby1'); 及时删。

坑3:两台机器 PG 小版本不一致

从库装的是 16.4,主库后来升到 16.6,某次重启后复制直接报版本不匹配。流复制要求主从小版本一致(大版本更不用说)。上生产前把两台的 apt 源锁到同一个版本,升级一起升。

六、再进一步的两个方向

  • 同步复制 :主库设 synchronous_standby_names='ANY 1 (standby1)',至少一台从库确认后才返回提交,防单点丢数据,代价是写入延迟。金融类场景再开,一般业务异步够用。
  • 故障切换 :手动 pg_promote() 能把从库提成主库,但生产别靠手速,上 Patroni 这类自动切换组件------正好也是 PGCCC PCP/PCM 课程里高可用模块的实操内容,想系统学的可以去看。

环境:PostgreSQL 16 on Ubuntu 22.04。命令以 PG 16 为准,15 及以前参数名略有差异(如 wal_keep_segments → wal_keep_size)。

相关推荐
IvorySQL16 小时前
PostgreSQL 日报 |RLS 机密性绕过漏洞(9 月 27 日)
数据库·postgresql
IvorySQL1 天前
去 IOE 的最后一公里:IvorySQL 5.4 × RISC-V 实测
数据库·人工智能·ai·postgresql·risc-v
jeffwang2 天前
不装分词插件,用 PostgreSQL 做中文商品搜索:bigram + 向量 + RRF,以及「单字搜不到」这个坑
搜索引擎·postgresql·go
柒和远方2 天前
NestJS + TypeORM 学习笔记:语法和类型不绕了
postgresql·orm·nestjs
Y002 天前
PostgreSQL 的锁:为什么你的 ALTER TABLE 会卡住,以及怎么查
数据库·postgresql
geovindu8 天前
sql: Transaction & Concurrency Patterns using postgresql 18
postgresql·数据库开发·数据库架构
thinking_talk8 天前
WorkBuddy应用生成背后的数据层:腾讯云PG
postgresql·腾讯云·云数据库
知识的搬运工旺仔9 天前
唯一索引与 NULL 值:PostgreSQL 主键约束与 NULLS NOT DISTINCT
数据库·后端·sql·postgresql
jnrjian9 天前
EDB postgresql TDE 加密的文件
postgresql