PostgreSQL 提供两种核心的复制机制:物理复制(Physical Replication)和逻辑复制(Logical Replication)。二者在原理、能力、适用场景和运维复杂度上存在显著差异。正确理解并选择合适的复制方案,是构建高可用、灾备、数据分发和多活架构的基础。

本文将从底层原理出发,系统对比物理复制与逻辑复制的工作机制、功能特性、配置方法、监控手段及典型应用场景,并提供实战案例与选型建议,助你全面掌握 PostgreSQL 复制技术体系。


一、复制的基本概念与目标

1.1 什么是复制?

复制是指将一个 PostgreSQL 实例(主库,Primary)上的数据变更,实时或近实时地同步到一个或多个其他实例(备库,Standby)的过程。

1.2 复制的核心目标

  • 高可用(HA):主库故障时,备库可快速接管服务;
  • 读写分离:将只读查询分流至备库,减轻主库压力;
  • 灾难恢复(DR):异地备库防止区域性故障导致数据丢失;
  • 数据分发:将部分表或数据同步至分析系统、缓存或其他数据库;
  • 零停机升级/迁移:通过复制实现平滑切换。

二、物理复制(Physical Replication)

2.1 工作原理:基于 WAL 的块级复制

物理复制的核心是 WAL(Write-Ahead Logging)日志的传输与重放。

  • 主库将每个事务产生的 WAL 记录写入磁盘;
  • 备库通过 流复制(Streaming Replication)或 归档复制(Archive Replication)接收 WAL;
  • 备库启动 startup 进程,逐条重放(replay)WAL 记录,修改数据文件的物理块(8KB page);
  • 备库的数据文件与主库完全一致(bit-for-bit identical)。

物理复制是“黑盒”复制:备库不关心 SQL 语义,只按字节重做 I/O 操作。

2.2 配置步骤

(1)主库配置(postgresql.conf)
wal_level = replica          # 必须为 replica 或 logical
max_wal_senders = 10         # 允许的最大 WAL 发送进程数
max_replication_slots = 5    # 复制槽数量(可选但推荐)
listen_addresses = '*'       # 允许远程连接
(2)主库创建复制用户
CREATE ROLE replicator WITH REPLICATION LOGIN PASSWORD 'strongpass';
(3)主库配置 pg_hba.conf
host replication replicator 192.168.1.0/24 md5
(4)备库初始化(使用 pg_basebackup)
pg_basebackup -h primary_host -U replicator -D /var/lib/postgresql/15/main -P -R -X stream
  • -R:自动生成 standby.signalprimary_conninfo
  • -X stream:同时复制 WAL 流,避免初始 gap。
(5)启动备库
pg_ctl start -D /var/lib/postgresql/15/main

2.3 关键特性

特性 说明
全库复制 整个集群(所有数据库、所有对象)被复制
版本一致性 主备必须相同大版本(如 15→15),小版本可不同
只读备库 备库默认只读(PG 15+ 支持逻辑解码在备库运行,但仍不可写)
延迟可控 可配置 recovery_min_apply_delay 实现延迟复制
支持同步提交 通过 synchronous_standby_names 实现强一致性

2.4 复制槽(Replication Slot)

  • 作用:防止主库过早清理 WAL 日志,避免备库因网络中断而“掉队”;
  • 类型:物理复制槽(pg_create_physical_replication_slot);
  • 风险:若备库长期离线,WAL 会无限堆积,导致磁盘写满。

启用复制槽(备库 recovery.conf 或 postgresql.auto.conf):

primary_slot_name = 'slot1'

主库创建:

SELECT * FROM pg_create_physical_replication_slot('slot1');

三、逻辑复制(Logical Replication)

3.1 工作原理:基于发布-订阅的行级复制

逻辑复制从 WAL 中解析出逻辑变更(INSERT/UPDATE/DELETE),以为单位进行复制。

  • 主库启用 逻辑解码(Logical Decoding),将 WAL 转换为逻辑变更流;
  • 用户创建 发布(Publication),指定要复制的表;
  • 备库创建 订阅(Subscription),连接到发布者;
  • 备库的 apply 进程 接收变更并执行 SQL 语句,更新本地表。

逻辑复制是“白盒”复制:备库知道每行数据的变化内容。

3.2 配置步骤

(1)主库配置
wal_level = logical          # 必须为 logical
max_replication_slots = 5
max_logical_replication_workers = 4
(2)主库创建发布
-- 发布所有表
CREATE PUBLICATION pub_all FOR ALL TABLES;

-- 或发布特定表
CREATE PUBLICATION pub_orders FOR TABLE orders, order_items;

表必须有主键REPLICA IDENTITY(否则 UPDATE/DELETE 无法定位行)。

(3)备库创建订阅
CREATE SUBSCRIPTION sub_orders
CONNECTION 'host=primary_host port=5432 user=replicator password=xxx dbname=mydb'
PUBLICATION pub_orders;
  • 备库会自动从主库拷贝初始数据(快照同步);
  • 同步完成后,开始流式接收变更。

3.3 关键特性

特性 说明
选择性复制 可按表、按列(PG 15+)复制
跨版本支持 主备可不同大版本(如 14 → 15),只要协议兼容
跨平台支持 可复制到不同操作系统、CPU 架构
备库可写 未被订阅的表可正常读写
冲突处理 若本地修改了被订阅的行,可能引发冲突(需手动解决)
不复制 DDL 表结构变更(ALTER TABLE)不会自动同步

3.4 REPLICA IDENTITY

当表无主键时,需显式设置如何标识行:

-- 使用所有列作为标识(开销大)
ALTER TABLE t REPLICA IDENTITY FULL;

-- 使用唯一索引
ALTER TABLE t REPLICA IDENTITY USING INDEX idx_unique;

否则 UPDATE/DELETE 将无法在备库执行。


四、物理复制 vs 逻辑复制:全面对比

维度 物理复制 逻辑复制
复制粒度 整个集群(块级) 表级(行级)
数据一致性 强一致性(WAL 重放) 最终一致性(异步)
主备版本 必须相同大版本 支持跨大版本
备库状态 只读 可读写(非订阅表)
DDL 同步 自动同步 不同步
初始化方式 pg_basebackup(全量文件拷贝) 自动快照同步(逻辑导出)
网络带宽 较高(传输整个 WAL) 较低(仅传输变更行)
适用场景 HA、DR、读写分离 数据分发、多活、异构同步
冲突风险 有(备库写入被订阅表)
监控视图 pg_stat_replication, pg_replication_slots pg_stat_subscription, pg_publication_*

五、典型应用场景

5.1 物理复制适用场景

(1)高可用架构(主备切换)
  • 使用 Patroni、repmgr 等工具实现自动故障转移;
  • 备库实时同步,RPO ≈ 0,RTO < 30 秒。
(2)读写分离
  • 应用将 SELECT 查询路由至备库;
  • 需注意复制延迟可能导致读到旧数据。
(3)异地灾备
  • 主数据中心 + 异地物理备库;
  • 结合 WAL 归档实现 PITR(时间点恢复)。

5.2 逻辑复制适用场景

(1)数据聚合与分发
  • 将多个业务库的订单表汇聚到中央分析库;
  • 只复制必要字段,减少带宽。
(2)数据库升级/迁移
  • 旧版本主库 → 新版本备库;
  • 切流前验证新版本兼容性。
(3)多活架构(Active-Active)
  • 两个数据中心互为逻辑订阅;
  • 需应用层保证无冲突写入(如按用户ID分片)。
(4)向异构系统同步
  • 通过自定义输出插件(如 wal2json),将变更发送至 Kafka;
  • 供下游 Flink、Elasticsearch 消费。

六、监控与运维

6.1 物理复制监控

-- 查看复制状态
SELECT * FROM pg_stat_replication;

-- 查看复制槽
SELECT * FROM pg_replication_slots;

-- 计算复制延迟(字节)
SELECT pg_wal_lsn_diff(pg_current_wal_lsn(), replay_lsn) AS bytes_lag
FROM pg_stat_replication;

-- 转换为时间延迟(需估算 WAL 生成速率)

6.2 逻辑复制监控

-- 查看订阅状态
SELECT * FROM pg_stat_subscription;

-- 查看发布表
SELECT * FROM pg_publication_tables;

-- 查看冲突(PG 15+)
SELECT * FROM pg_stat_subscription_conflicts;

6.3 常见问题处理

(1)物理备库延迟高
  • 检查网络带宽;
  • 备库 I/O 性能是否不足;
  • 主库 max_wal_senders 是否耗尽。
(2)逻辑复制冲突
  • 备库日志出现 “conflicting key value”;
  • 解决方案:
    • 手动跳过:ALTER SUBSCRIPTION sub_name SKIP (lsn='...');
    • 修改应用逻辑,避免双写。
(3)WAL 磁盘写满
  • 物理复制:检查复制槽是否卡住;
  • 逻辑复制:检查订阅是否停止;
  • 临时解决方案:pg_drop_replication_slot('slot_name');(慎用!)

七、高级特性与未来方向

7.1 PG 15+ 增强

  • 逻辑复制支持列过滤
    CREATE PUBLICATION pub1 FOR TABLE t (id, name); -- 只复制 id, name
    
  • 备库支持逻辑解码:可在物理备库上启动逻辑复制,实现级联分发。

7.2 双向复制(Bi-Directional Replication)

  • 官方不直接支持;
  • 可通过 BucardoLondiste自定义触发器+队列 实现;
  • 需严格设计冲突避免策略。

7.3 与外部工具集成

  • Debezium:基于逻辑解码的 CDC 工具,输出 JSON 到 Kafka;
  • pglogical(2ndQuadrant):增强版逻辑复制,支持 DDL 同步、冲突检测等。

八、选型建议:如何选择?

你的需求 推荐方案
高可用、故障自动切换 物理复制 + Patroni
读写分离,降低主库负载 物理复制
仅同步部分表到分析库 逻辑复制
跨版本升级(14 → 16) 逻辑复制
多数据中心双向写入 逻辑复制 + 应用层分片
向 Kafka/Elasticsearch 同步 逻辑解码 + wal2json

黄金法则

  • 强一致性、简单可靠 → 选物理复制;
  • 灵活性、选择性、跨版本 → 选逻辑复制。

总结:PostgreSQL 的物理复制与逻辑复制并非相互替代,而是互补共存的技术:

  • 物理复制是高可用的基石,提供简单、高效、强一致的全量同步;
  • 逻辑复制是数据流动的桥梁,支持精细化、跨平台、可编程的数据分发。

在实际架构中,甚至可混合使用

  • 主库 → 物理备库(用于 HA);
  • 主库 → 逻辑订阅者(用于数据分析);
  • 物理备库 → 逻辑订阅者(级联分发,减轻主库压力)。

掌握二者原理与边界,方能构建弹性、可靠、高效的现代数据基础设施。

Logo

助力广东及东莞地区开发者,代码托管、在线学习与竞赛、技术交流与分享、资源共享、职业发展,成为松山湖开发者首选的工作与学习平台

更多推荐