PostgreSQLNotes

第 22 章:逻辑复制

zjc 于 2026-01-22 发布

这是《PostgreSQL 零基础实战指南》的独立章节版。本章从概念、实操和生产排查三个视角展开,代码块保留了原书可直接运行的版本。 逻辑复制发布逻辑变更,而不是物理页变化。它支持按库表选择、跨版本升级和异构消费,但语义限制更多。

22.1 架构

Publisher
  logical decoding -> publication
          |
Replication protocol
          |
Subscriber
  apply worker -> subscription

22.2 发布

发布端配置:

wal_level = logical
max_replication_slots = 10
max_wal_senders = 10

创建发布:

CREATE PUBLICATION sales_pub
FOR TABLE orders, order_items;

只发布部分操作:

ALTER PUBLICATION sales_pub SET (publish = 'insert, update');

22.3 订阅

CREATE SUBSCRIPTION sales_sub
CONNECTION 'host=publisher.internal port=5432 dbname=shop user=replicator password=strong-password sslmode=require'
PUBLICATION sales_pub;

初始数据会按发布表复制,之后应用增量逻辑变更。

22.4 冲突处理

订阅端遇到主键冲突或约束错误时,apply worker 会停止:

ERROR: duplicate key value violates unique constraint

处理方式:

  1. 查看订阅端错误;
  2. 删除或修正冲突行;
  3. 恢复 apply;
  4. 记录根因;
  5. 必要时重建订阅。

22.5 支持与限制

常见限制:

操作 逻辑复制行为
INSERT 支持
UPDATE 需要副本标识
DELETE 需要副本标识
DDL 不会自动发布
序列 不自动同步状态
大对象 版本和支持有限
TRUNCATE 取决于发布配置和版本

表必须有主键或唯一索引作为副本标识:

ALTER TABLE orders REPLICA IDENTITY USING INDEX uq_orders_order_no;

22.6 监控

发布端:

SELECT * FROM pg_stat_replication;
SELECT slot_name, plugin, database, active
FROM pg_replication_slots;

订阅端:

SELECT * FROM pg_stat_subscription;

关注:

  1. apply 延迟;
  2. 复制槽保留 WAL;
  3. 冲突错误;
  4. worker 状态;
  5. 表结构一致。

22.7 跨版本升级

旧版本 Publisher -> 新版本 Subscriber

流程:

  1. 新库建表和索引;
  2. 建发布和订阅;
  3. 等初始同步;
  4. 追平增量;
  5. 短停写;
  6. 校验数据;
  7. 切换应用;
  8. 同步序列;
  9. 删除订阅。

22.8 多写入与分区订阅

逻辑复制天然不防止多写入冲突。双向复制需要冲突解决策略和业务分区,不能只靠数据库默认行为。

本章小结

逻辑复制适合选择性表复制、跨版本升级和下游同步。它不复制 DDL 和序列状态,且依赖副本标识。生产必须监控复制槽、apply 延迟和冲突。

思考题

  1. 物理复制和逻辑复制有什么区别?
  2. REPLICA IDENTITY 有什么作用?
  3. 订阅端冲突如何处理?
  4. 为什么序列要单独处理?
  5. 逻辑复制升级的切换步骤是什么?