Dimitri Fontaine:使用Postgres逻辑复制整合数据库

Dimitri Fontaine:使用Postgres逻辑复制整合数据库

💡 原文英文,约6800词,阅读约需25分钟。
📝

内容提要

本文介绍用PostgreSQL逻辑复制将多个数据库整合到单一数据仓库。每个应用在源端有独立schema,仓库按应用建schema并各建一个订阅。由于订阅无法重命名表,命名须在源端完成。Postgres 15的列清单和行过滤器可排除敏感字段与无关租户数据,但过滤器仅对之后变更生效。DDL和序列不会复制,需手动处理;可用队列表加触发器模拟pglogical的DDL复制。Postgres 16支持从物理备库解码,减轻主库负担。

🔎

延伸解读

源端 schema 命名:整合前的必要准备

订阅无法重命名表,仓库端必须使用与源端相同的 schema 和表名。若应用表位于 public,需先在源端为应用创建独立 schema 并迁移表,再通过角色 search_path 保持应用无感知。若无法修改源端,则只能选择在仓库端为每个源建独立数据库,或引入重命名组件。

行过滤与列清单:生效时机与陷阱

Postgres 15 的行过滤和列清单可排除敏感字段与无关租户数据,但仅对之后变更生效。已复制的旧数据不会自动清理,需手动删除。若过滤列不在主键中,必须创建包含该列的唯一索引并设为 replica identity,否则更新会失败。

DDL 与序列:手动同步的代价

逻辑复制不复制 DDL 和序列。添加列时需先在订阅端执行,否则 apply worker 会停止并阻塞后续事务;删除列则相反。序列不同步会导致本地插入主键冲突。可用队列表加触发器模拟 DDL 复制,但需注意 search_path 差异和语句拆分问题。

CDC 负载与备库解码

Postgres 16 支持在物理备库上创建逻辑槽,将 CDC 消费者负载从主库转移。备库需配置与主库一致的 max_worker_processes、wal_level = logical 和 hot_standby_feedback = on,否则可能启动失败或槽失效。Postgres 19 的 effective_wal_level 可简化 wal_level 设置,但其他参数仍需手动调整。

❓

Q&A

如何用PostgreSQL逻辑复制将多个数据库整合到一个数据仓库?

每个应用在源端拥有独立schema,仓库为每个应用创建同名schema并各建一个订阅。由于订阅无法重命名表,必须在源端将表放入应用专属schema(如shopapp),并设置角色search_path,使应用无感知。仓库端手动创建相同表结构,然后为每个应用创建订阅。

Postgres 15的列清单和行过滤器在逻辑复制中怎么用?有什么限制?

在发布端使用列清单排除敏感字段(如email、phone),用行过滤器只发送特定租户数据(如tenant='eu')。限制:过滤器仅对之后变更生效,已复制的旧数据不会自动删除;行过滤器使用的列必须包含在replica identity中,否则更新会报错;列清单不能用于FOR TABLES IN SCHEMA的发布。

逻辑复制中DDL和序列为什么不会自动复制?如何解决?

Postgres核心不支持DDL复制,因为缺少将DDL文本通过WAL消息传递并重放的机制。序列也不会复制,可能导致主键冲突。解决方法:DDL可用队列表加触发器模拟pglogical的方式,在源端用事件触发器将DDL语句插入队列表,订阅端用ENABLE ALWAYS触发器执行;序列需手动同步或等待Postgres 19的序列复制功能。

如何将整合后的仓库变更再导出为CDC流?

在仓库上创建发布(如cdc_pub)覆盖所有schema,并创建逻辑槽(pgoutput或test_decoding)。消费者读取槽时需设置origin=any,否则只会看到本地写入而忽略复制应用的数据。注意:大事务会流式传输,消费者需能处理回滚;Postgres 16起逻辑槽可建在物理备库上以减轻主库负担。

在物理备库上创建逻辑槽需要哪些配置?

需要:备库的max_worker_processes至少与主库相同;备库自身设置wal_level=logical;hot_standby_feedback=on以防止主库vacuum删除所需行;创建槽时可能需在主库执行pg_log_standby_snapshot()。Postgres 19引入effective_wal_level,可自动提升WAL级别,但其他设置仍需手动。

逻辑复制中表结构变更(如加列)时,发布端和订阅端应该谁先执行?

添加列时,订阅端先执行,否则应用工作进程会因缺少列而停止,后续事务排队;删除列时,发布端先执行,订阅端保留的列会变为NULL,之后可手动删除。顺序错误会导致复制中断,需手动修复。

🏷️

标签

➡️

继续阅读