CentOS+PG 11级联复制配置失败求助:s1=>s2停摆s2=>s3未生效
首先明确:PostgreSQL 11完全支持逻辑复制的级联配置(也就是把订阅端再作为发布端向下游复制),你遇到的s1→s2复制停止、s2→s3复制未生效的问题,都是可以通过排查配置解决的,并非方案本身不可行。
我来拆解可能的问题点和对应的解决步骤:
一、先解决s2作为发布端的核心前提
s2要成为发布端,必须满足一个关键配置:wal_level必须设为logical。之前s2只是作为订阅端,可能默认的wal_level是replica(这对订阅端来说足够,但发布端需要生成逻辑日志,必须开logical)。
检查&修改步骤:
- 登录s2的PostgreSQL,执行:
SHOW wal_level;
- 如果结果不是
logical,修改postgresql.conf文件:
wal_level = logical
- 重启s2的PostgreSQL服务:
systemctl restart postgresql-11
这个步骤是s2能向下游s3发布数据的基础,没开的话s2根本生成不了逻辑复制需要的日志,s2→s3自然无法生效;同时修改后重启服务可能会中断s1→s2的原有连接,这也是你看到s1→s2复制停止的原因之一。
二、修复s1→s2的复制连接
s2重启后,原有订阅连接可能中断,需要重新激活:
- 在s2上查看订阅状态:
SELECT subname, status FROM pg_stat_subscription;
如果status不是streaming,说明订阅已中断。
2. 先禁用再启用订阅(替换成你的订阅名称,比如s1_to_s2_sub):
ALTER SUBSCRIPTION s1_to_s2_sub DISABLE; ALTER SUBSCRIPTION s1_to_s2_sub ENABLE;
- 也可以刷新订阅确保同步最新的发布配置:
ALTER SUBSCRIPTION s1_to_s2_sub REFRESH PUBLICATION;
- 到s1上检查复制状态,确认s2的连接是否恢复:
SELECT usename, application_name, state FROM pg_stat_replication;
如果能看到s2的连接且state为streaming,说明s1→s2的复制已恢复。
三、排查s2→s3复制未生效的问题
解决完s1→s2的问题后,再来处理s2→s3的复制,常见问题点如下:
1. s2的发布配置是否正确
在s2上确认发布已创建且包含目标表:
SELECT pubname, pubtables FROM pg_publication;
确保你要复制的表在pubtables列表里,如果是创建发布时用了FOR ALL TABLES,要确认新表是否自动加入(PG11默认是开启的)。
2. s3的订阅配置是否正确
- 检查s3上的订阅连接字符串是否正确(主机、端口、数据库名、用户密码都不能错):
SELECT conninfo FROM pg_subscription;
- 如果s3上的表还没有数据,创建订阅时要确保
COPY DATA选项开启(默认是开启的,但如果之前手动关闭了,需要显式指定):
CREATE SUBSCRIPTION s2_to_s3_sub CONNECTION 'host=s2_ip port=5432 dbname=your_db user=repl_user password=xxx' PUBLICATION s2_pub WITH (COPY_DATA = true);
3. 权限与网络问题
- s2的
pg_hba.conf必须允许s3的IP连接,添加规则:
host your_db repl_user s3_ip/32 md5
然后重载PG配置:
systemctl reload postgresql-11
- 确保s2和s3的防火墙都开放了5432端口,避免网络阻塞。
- 用于复制的用户必须拥有
REPLICATION权限,以及对目标表的SELECT权限。
4. 表结构与约束问题
PG11的逻辑复制要求复制的表必须有主键或唯一约束(用于识别行),如果s2上的表没有这些约束,发布和订阅都会失败。检查s2上的表:
SELECT tablename, conname FROM pg_constraint WHERE contype IN ('p','u') AND conrelid = 'your_table'::regclass;
如果没有主键/唯一约束,需要添加后再重新创建发布和订阅。
最后注意事项
- 不要在s2上对来自s1的复制表进行随意写操作,否则会导致s1与s2的数据不一致,同时这些写操作会被同步到s3,破坏整个复制链的数据一致性。
- 所有操作完成后,在s1插入测试数据,依次检查s2、s3是否同步收到数据,验证整个复制链的有效性。
内容的提问来源于stack exchange,提问作者Edilmar Alves

