Dimitri Fontaine:PostgreSQL逻辑复制的十年演进

Dimitri Fontaine:PostgreSQL逻辑复制的十年演进

💡 原文英文,约6100词,阅读约需22分钟。
📝

内容提要

本文回顾PostgreSQL逻辑复制十年演进:从10版引入核心复制,到15版支持行/列过滤、16版支持origin防循环、18版提供冲突计数、19版测试序列复制。作者以“中心-工作节点”架构为例,展示如何用核心功能替代pglogical等扩展,并对比Citus:后者自动化分片与DDL传播,但工作节点无法独立运行,而逻辑复制保留节点自治。

🔎

延伸解读

逻辑复制与Citus:自治性与透明性的权衡

文章对比了基于核心逻辑复制的中心-工作节点架构与Citus。逻辑复制保留工作节点的完全自治,每个节点是独立Postgres,可独立处理本地写入,但代价是数据存在第二份副本(中心节点)。Citus则通过分片和协调器自动化管理,应用通常只连接协调器,工作节点不设计为独立运行,数据只有一份。选择取决于工作节点是否需要自治:若工作节点因区域、大客户或合规要求必须独立运行,逻辑复制更合适;若工作节点仅是数据存放地,Citus更透明。

冲突计数器的实用解读:哪些冲突会静默导致数据分歧

Postgres 18为逻辑复制引入了按冲突类型计数的统计视图pg_stat_subscription_stats。文章通过实验区分了两类冲突:update_missing、delete_missing、update_origin_differs、delete_origin_differs这四种不会停止复制,但意味着数据已经分歧,且apply_error_count保持为零,容易被监控忽略;而insert_exists、update_exists、multiple_unique_conflicts会停止apply

序列复制在19版的局限:不解决工作节点自铸ID

Postgres 19测试了序列复制,但文章指出其方向是从发布者到订阅者传输序列值,而中心-工作节点架构中工作节点需要自己生成ID,因此序列复制对此场景无帮助。在18及之前,工作节点自铸ID需依赖应用层方案,如模偏移序列或UUIDv7。模偏移需预留足够增量,否则新增工作节点可能冲突;UUIDv7在18版可用,时间有序且无需协调,但占用16字节。文章强调,若工作节点为hub拥有的表生成ID,会与复制行冲突,因此规则是工作节点不为hub表铸ID。

添加工作节点的锁风险与操作顺序

文章通过实验对比了两种添加分区方式的锁级别:create table ... partition of 会对父表加ACCESS EXCLUSIVE锁,阻塞所有访问usage_events的操作,包括正在运行的apply worker;而attach partition只加SHARE UPDATE EXCLUSIVE锁,不会阻塞现有apply worker。因此推荐的操作顺序是:先独立创建表,添加与分区边界匹配的check约束(可跳过验证扫描),然后attach partition,最后创建订阅。这样现有apply

Q&A

PostgreSQL逻辑复制从哪个版本开始引入?

PostgreSQL 10(2017年)首次引入逻辑复制。

PostgreSQL 15在逻辑复制方面增加了什么功能?

PostgreSQL 15增加了行过滤和列过滤功能,允许发布部分行或列,并支持发布整个模式。

如何避免双向逻辑复制中的循环?

在创建订阅时设置origin = none,这样发布者只发送本地产生的更改,不发送通过复制到达的更改。需要在两个方向的订阅上都设置该选项。

PostgreSQL 18如何帮助监控逻辑复制冲突?

PostgreSQL 18在pg_stat_subscription_stats中增加了每种冲突类型的计数器,如confl_insert_exists、confl_update_exists等,可以监控冲突情况。

逻辑复制和Citus在架构上有什么主要区别?

逻辑复制保留工作节点的自治性,每个节点是独立的PostgreSQL服务器,可以独立运行;而Citus的工作节点是分片存储节点,由协调器管理,不能独立运行。

PostgreSQL 19在逻辑复制方面有什么新特性?

PostgreSQL 19(测试版)支持序列复制,使序列值可以随表一起复制。

🏷️

标签

➡️

继续阅读