PostgreSQL:一文掌握物理复制与逻辑复制
PostgreSQL提供物理复制和逻辑复制两种核心机制。物理复制基于WAL日志实现块级同步,适用于高可用、灾备等全库复制场景,要求主备版本一致且备库只读。逻辑复制通过发布-订阅模式实现表级行同步,支持跨版本、选择性复制和备库写入,适用于数据分发、多活架构等场景。二者在数据一致性、版本要求、备库状态等方面存在显著差异。正确选择复制方案需根据具体需求,如高可用推荐物理复制,异构系统集成则适合逻辑复制。
文章目录
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.signal和primary_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)
- 官方不直接支持;
- 可通过 Bucardo、Londiste 或 自定义触发器+队列 实现;
- 需严格设计冲突避免策略。
7.3 与外部工具集成
- Debezium:基于逻辑解码的 CDC 工具,输出 JSON 到 Kafka;
- pglogical(2ndQuadrant):增强版逻辑复制,支持 DDL 同步、冲突检测等。
八、选型建议:如何选择?
| 你的需求 | 推荐方案 |
|---|---|
| 高可用、故障自动切换 | 物理复制 + Patroni |
| 读写分离,降低主库负载 | 物理复制 |
| 仅同步部分表到分析库 | 逻辑复制 |
| 跨版本升级(14 → 16) | 逻辑复制 |
| 多数据中心双向写入 | 逻辑复制 + 应用层分片 |
| 向 Kafka/Elasticsearch 同步 | 逻辑解码 + wal2json |
黄金法则:
- 要强一致性、简单可靠 → 选物理复制;
- 要灵活性、选择性、跨版本 → 选逻辑复制。
总结:PostgreSQL 的物理复制与逻辑复制并非相互替代,而是互补共存的技术:
- 物理复制是高可用的基石,提供简单、高效、强一致的全量同步;
- 逻辑复制是数据流动的桥梁,支持精细化、跨平台、可编程的数据分发。
在实际架构中,甚至可混合使用:
- 主库 → 物理备库(用于 HA);
- 主库 → 逻辑订阅者(用于数据分析);
- 物理备库 → 逻辑订阅者(级联分发,减轻主库压力)。
掌握二者原理与边界,方能构建弹性、可靠、高效的现代数据基础设施。
更多推荐

所有评论(0)