1 PostgreSQL 中的物理复制与逻辑复制:机制、差异与选型

本文从 WAL(预写式日志) 出发,说明 物理复制(通常即流复制 / streaming replication)逻辑复制(logical replication) 各自如何产生、传输与应用变更,并标出常见误区与版本相关行为。阅读后你应能回答:谁在解码 WAL、副本上跑的是什么、能过滤什么、DDL 与冲突怎么处理


1.1 共同基础:WAL 是什么

  • WAL(Write-Ahead Log):事务提交前,先把足够的信息持久化到日志,崩溃后可重放以恢复一致性。
  • 概念分层:WAL 是「存储与恢复」层面的日志;其上可叠加 物理重放(按页/低层记录恢复)或 逻辑解码(把变更解释为对行的插入/更新/删除等)。

准确性:不同大版本在 WAL 内部记录格式、可选特性(如压缩、某些子系统的记录类型)上会演进;下文描述的是 PostgreSQL 主流架构思路,具体对象名以你使用的版本文档为准。


1.2 物理复制(Physical Replication)一般指什么

在 PostgreSQL 社区语境里,物理复制几乎总是指:备库按与主库相同的物理存储布局重放 WAL,典型实现是 流复制(streaming replication)(持续把 WAL 段流式传给备库),辅以 pg_basebackup 等做初始基线。

1.2.1 工作方式(心智模型)

  • 主库生成 WAL;备库是「整个数据目录」级别的镜像演进(同一集群、同一套 catalog 与数据文件语义)。
  • 备库在恢复模式下应用 WAL,通常表现为 热备(hot standby):可读,默认不可写(除非 promoted 或可写副本等架构)。

1.2.2 你能得到什么

  • 强一致副本形态:与主库在存储层「同构」,适合 HA 故障切换、只读负载分担、备份窗口卸载
  • 整库复制:一个 primary 对应 standby 时,是实例级复制,不是「只订阅某几张表」为第一公民模型(表级过滤属于逻辑层思路)。

1.2.3 同步策略(与「物理/逻辑」正交但常一起考)

  • 异步:提交不必等备库刷盘;延迟存在。
  • 同步synchronous_standby_names 等配置下,满足条件的同步副本确认前事务可阻塞提交(细节与 remote_apply / on / quorum 等级别有关,以官方文档为准)。

1.2.4 典型组件与名词

  • WAL sender / WAL receiver:流式传输端与接收端进程。
  • 复制槽(replication slot):物理槽用于保留 WAL,防止主库过早回收导致备库追不上(需监控槽滞后与磁盘)。
  • pg_basebackup:获取基线数据目录 + 启动流或配合归档的初始同步。

1.3 逻辑复制(Logical Replication)是什么

逻辑复制不追求「字节级同一数据文件」,而是:从 WAL 中解码出逻辑变更(对某表的 INSERT/UPDATE/DELETE),再通过复制协议在订阅端应用。

1.3.1 工作方式(心智模型)

  • 发布端(publisher):定义 publication(发布哪些表;新版本可带行/列过滤等能力,见下文版本提示)。
  • 订阅端(subscriber):定义 subscription,连到上游拉取变更并应用。
  • 解码依赖 逻辑解码(logical decoding) 与输出插件;内置路径常用 pgoutput(PostgreSQL 原生协议插件)。

1.3.2 你能得到什么

  • 部分复制:可选择表集合;适合 多租户拆分、汇聚、跨版本迁移(在支持矩阵内)、异构下游 等。
  • 副本可写:订阅库上未被订阅覆盖的表可本地读写;与物理备库默认只读不同。
  • 版本边界更灵活:逻辑复制在官方支持矩阵内可跨一定大版本(以发行说明为准),而物理流复制通常要求主备同大版本(升级通过逻辑复制或 pg_upgrade 等另议)。

1.3.3 关键概念:Replica Identity

逻辑复制要把 UPDATE/DELETE 变成「可定位旧行」的流,需要 replica identity

  • DEFAULT:有主键则用主键列;有唯一且非部分索引则可用其列集(细节见文档);否则解码 UPDATE/DELETE 可能受限。
  • FULL:用整行作为键;日志与带宽开销更大,但适合无主键表(仍要评估性能)。
  • NOTHING:不记录旧行键信息,无法合理传播 UPDATE/DELETE(对这类表逻辑复制通常不适用)。

1.3.4 DDL 与限制(高频考点)

  • 逻辑复制以表数据变更为主DDL 不会自动像 DML 一样复制(CREATE TABLE、改列类型等需另行策略:手工、事件触发器、外部工具或新版本特性)。
  • 序列(sequence):历史行为里 SERIAL/IDENTITY 的序列值 需要专门理解(常见做法是显式同步序列或在切换时 setval);具体以版本文档「Logical Replication」章节为准。
  • 大对象(large objects):通常不在逻辑复制默认路径内。
  • 冲突:订阅端若对同一主键已有不同行,应用变更可能失败;需监控与重试策略。

1.4 对照表:物理 vs 逻辑(抓住本质)

维度物理复制(流复制)逻辑复制
解码位置与内容备库按 WAL 物理恢复发布端解码为逻辑行变更
复制粒度实例 / 数据目录级表级 publication(可子集)
备库形态典型为热备,默认只读订阅库可混合读写(非复制表)
DDL随 WAL 隐含一致(同一 catalog)不自动复制 DDL(需额外流程)
典型用途HA、只读扩展、灾备部分同步、汇聚、滚动升级辅助
版本关系主备通常同大版本在支持矩阵内可跨大版本(需验证)

表为教学归纳;生产约束以官方矩阵与实测为准。


1.5 复制槽:物理槽与逻辑槽不要混谈

  • 物理复制槽:为 standby 保留 WAL,避免被 CHECKPOINT/回收机制删掉导致断流。
  • 逻辑复制槽:为 逻辑解码消费位点 保留 WAL;长期不消费会膨胀 WAL 与磁盘。

两者都叫 slot,但消费者与监控指标不同;运维上要分别建告警。


1.6 监控与排障:两边都问的三个问题

  • 滞后(lag):物理看 pg_stat_replicationwrite/flush/replay_lag;逻辑看订阅端 pg_stat_subscription_stats 等(字段随版本演进)。
  • WAL 堆积原因:网络、磁盘、单线程应用、大事务、解码慢、冲突停写等。
  • 一致性语义:同步提交级别、remote_apply 与「读己之写」在只读副本上的行为,以文档为准,不要凭直觉写进 SLA。

1.7 版本提示(阅读官方 Release Notes 时重点搜)

  • PostgreSQL 10:逻辑复制进入内核主线的重要版本节点(此前更多依赖外部逻辑解码生态)。
  • PostgreSQL 15+:逻辑发布订阅能力持续增强(例如行过滤、列列表等方向——以你所用确切小版本的 Release Notes / Current 文档 为准,不在此绑定具体语法以免与你环境不一致)。

准确性原则:涉及 CREATE SUBSCRIPTION ... WITH (...) 的参数默认值、并行应用 worker、两阶段提交与逻辑复制交互等,请以 当前大版本官方文档 为唯一权威。


1.8 选型建议(工程向)

  • 首要目标是机架级 HA 与只读扩展:默认先设计 物理流复制 + 监控 + 切换
  • 需要跨库汇聚、表级同步、订阅端本地扩展表、或在支持矩阵内做滚动升级辅助:评估 逻辑复制,并接受 DDL 流程化与冲突治理 成本。
  • 二者可并存:例如 HA 仍走物理副本,分析侧用逻辑订阅拉部分表(注意上游 WAL 与解码负载)。

1.9 常见误解纠正

  • 误解:「逻辑复制更先进,应替代物理复制。」正解:目标不同;HA 机架级切换仍以物理副本常见且路径成熟。
  • 误解:「逻辑复制等于行级 CDC。」正解:形态相近,但 PostgreSQL 逻辑复制是内置订阅模型,不等价于所有 Debezium/Kafka 生态语义;对接外部系统常仍用 逻辑解码插件 + 导出格式
  • 误解:「有主键就一定能逻辑复制 UPDATE/DELETE。」正解:还要 publication 包含该表、权限、replica identity 配置、以及订阅端约束与冲突处理等。

1.10 建议实验(加深理解)

  • 起两个本地实例(或同实例两库),建立 publication/subscription,观察 pg_replication_slotspg_stat_replication / 订阅统计视图。
  • 故意在订阅端制造主键冲突,观察应用错误与 WAL 滞留。
  • 对比 pg_basebackup + 流复制 初始搭建与 逻辑订阅 初始数据同步(copy_data 等选项以文档为准)在时间与锁上的差异。

1.11 参考入口(权威)

  • 官方手册章节:High Availability, Load Balancing, and ReplicationLogical ReplicationWarm StandbyReplication Progress Monitoring
  • 以你部署的 确切 PostgreSQL 版本号 阅读对应版本的 HTML/PDF 文档,避免混读导致参数默认值错误。

1.12 文档说明

本文为概念与运维向梳理,不包含可直接执行的生产级配置片段,以免与你的版本默认值偏离;落地时请粘贴你环境的 SHOW server_version; 并对照该版本文档逐条校验。