PostgreSQL 12逻辑复制copy_data=false不生效,订阅时报唯一键冲突
解决PostgreSQL订阅copy_data=false仍报唯一键重复的问题
问题根源
copy_data=false 只是跳过订阅创建时的初始全量数据同步,但发布端在备份时间点之后产生的变更(比如更新、插入操作),如果对应的主键在订阅端已存在,同步时就会触发唯一键约束冲突。比如你订阅端备份里已有id=2的记录,发布端在备份后对id=2做过更新,这条变更同步到订阅端时就会报错。
解决步骤
1. 先暂停订阅
在pgAdmin里选中目标订阅,右键选择「暂停」;或者直接执行SQL命令:
ALTER SUBSCRIPTION your_subscription_name DISABLE;
2. 处理冲突变更
有两种方式可选,按需选择:
- 临时跳过冲突(快速恢复):
临时开启订阅的错误跳过功能,让订阅忽略冲突继续同步后续变更:
ALTER SUBSCRIPTION your_subscription_name SET (skip_errors = 'true');
然后重新启用订阅:
ALTER SUBSCRIPTION your_subscription_name ENABLE;
等订阅追上发布端最新数据后,记得关闭错误跳过(避免后续真的有数据问题被忽略):
ALTER SUBSCRIPTION your_subscription_name SET (skip_errors = 'false');
- 调整同步起点(保证数据一致性):
先找到订阅端备份对应的发布端LSN(日志序列号)——如果用pg_basebackup做的备份,备份目录里的backup_label文件会记录这个值。然后修改订阅的同步起点为备份时的LSN,确保只同步备份之后的新变更:
ALTER SUBSCRIPTION your_subscription_name SET PUBLICATION your_publication_name WITH (copy_data = false, start_pos = '你的备份LSN值');
再启用订阅:
ALTER SUBSCRIPTION your_subscription_name ENABLE;
3. 验证数据一致性
同步完成后,对比订阅端和发布端的表数据,确保没有遗漏或冲突:
-- 对比单表记录数 SELECT COUNT(*) FROM your_table_name; -- 在订阅端执行 -- 切换到发布端执行同样命令,确认记录数一致 -- 检查主键差异 SELECT id FROM your_table_name EXCEPT SELECT id FROM 发布端数据库名.your_table_name; -- 订阅端独有的ID SELECT id FROM 发布端数据库名.your_table_name EXCEPT SELECT id FROM your_table_name; -- 发布端独有的ID
内容的提问来源于stack exchange,提问作者Sultan Zhumatayev
相关产品推荐
相关产品推荐

