首页/数据/数据工程与 ETL 速查/PostgreSQL 逻辑复制与复制槽
CDC 与同步53 条

PostgreSQL 逻辑复制与复制槽

PostgreSQL 变更捕获基于 WAL 逻辑解码:wal_level=logical 后可用发布/订阅(CREATE PUBLICATION / CREATE SUBSCRIPTION)或逻辑解码插件(pgoutput、wal2json)输出变更;复制槽记录消费位点,槽长时间不消费会导致 WAL 持续堆积占用磁盘。

PostgreSQL 逻辑复制是什么

PostgreSQL 的变更捕获基于 WAL 逻辑解码:把 wal_level 设为 logical 后,可以用发布/订阅(CREATE PUBLICATION / CREATE SUBSCRIPTION)在库之间同步表级变更,也可以用逻辑解码插件(内置 pgoutput、第三方 wal2json)把变更流交给外部工具。复制槽记录消费进度,这是它最需要留意的特性:槽建了没人消费,WAL 会一直不回收,直到把磁盘写满。

基本信息

前提配置wal_level=logical,修改后需要重启实例
发布订阅CREATE PUBLICATION 声明表,CREATE SUBSCRIPTION 订阅并复制
初始数据订阅默认会复制初始表数据,目标表已有数据时应设为不复制初始数据
复制槽记录消费位点;槽未推进则 WAL 不回收
行标识REPLICA IDENTITY 决定 UPDATE/DELETE 事件能带出多少旧值
DDL 不同步逻辑复制不传播表结构变更,DDL 需在两侧手工维护

典型使用场景

  • 库到库同步:把业务库指定表实时同步到分析库或另一个实例
  • CDC 接入:用解码插件把变更流交给外部采集工具,替代触发器方案
  • 大版本升级过渡:用逻辑复制做跨版本迁移并缩短停机窗口
  • 按表选择性同步:只复制关心的表,不复制全实例
  • 多目标分发:同一份发布可被多个订阅端使用

发布订阅与复制槽

发布订阅与复制槽
-- 源端:必须为 logical 级别,修改参数后重启
SHOW wal_level;
-- 只发布需要同步的表
CREATE PUBLICATION pub_orders FOR TABLE app.orders;

-- 目标端:订阅发布(目标表已有数据时关闭初始复制)
CREATE SUBSCRIPTION sub_orders
  CONNECTION 'host=10.0.0.5 dbname=app user=repl password=***'
  PUBLICATION pub_orders
  WITH (copy_data = false);

-- 源端查看槽状态与保留位点:active 为 false 时要警惕
SELECT slot_name, active, restart_lsn, confirmed_flush_lsn
FROM pg_replication_slots;

旧值与槽清理

旧值与槽清理
-- UPDATE/DELETE 需要完整旧值时,把行标识设为 FULL
ALTER TABLE app.orders REPLICA IDENTITY FULL;

-- 删除不再使用的槽(会立即释放被该槽占住的 WAL)
SELECT pg_drop_replication_slot('sub_orders');

-- 观察 WAL 堆积与槽数量上限
SELECT COUNT(*) AS slot_cnt FROM pg_replication_slots;
SHOW max_replication_slots;

关键配置与影响

配置作用影响
wal_level决定能否逻辑解码非 logical 时无法建发布与槽
max_replication_slots实例允许的槽数量上限数量不足时新槽创建失败
REPLICA IDENTITY控制 UPDATE/DELETE 能带出的旧值默认设置下旧值缺失,下游无法比对
复制槽活跃状态指示是否有人在消费inactive 时 WAL 持续堆积
建槽后没人消费等于 WAL 一直不回收,直到写满磁盘导致实例拒绝写入:删除槽前先确认没有订阅仍在使用,删除操作不可回滚。
逻辑复制不传播 DDL:源端加列、改类型后必须在订阅端同步执行,否则复制会中断报错。把 DDL 变更纳入两侧统一的发布流程是关键。

易错点

  • 开槽未消费导致 WAL 堆积写满磁盘,排查时先看 pg_replication_slots
  • REPLICA IDENTITY 保持默认,UPDATE/DELETE 事件缺少旧值字段
  • 源端改了表结构(DDL)未在订阅端同步执行,复制中断且报错指向不明
  • wal_level 未设为 logical 就尝试建发布,报错后误以为是权限问题
  • 复制槽数量达到上限,新订阅创建失败,故障时无法临时加链路

数据来源与参考

  • PostgreSQL 官方文档(Logical Replication)
  • Debezium 官方文档(PostgreSQL Connector)
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌