本文讨论富士通 OSS 团队与 PostgreSQL 开源社区合作为 PostgreSQL 15 添加的新功能,以实现模式中所有表的逻辑复制。

目录
背景
PostgreSQL 14 支持数据库中特定表或所有表从发布者到订阅者的逻辑复制。如果用户想要发布存在于一个模式或多个模式中的表,他们必须通过查询数据库手动准备表列表,然后使用手动准备的列表创建发布。
当模式中只有几个表时,准备列表是快速和容易的,但如果有数百或数千个表,那么这将是一项繁琐的任务。
为了克服这个问题,即将推出的 PostgreSQL 15 将添加选项ALL TABLES IN SCHEMA,这将允许指定一个或多个模式,其表由发布者选择用于向订阅者发送数据。
注意:在这篇文章中,我将把这个新特性称为模式发布,它允许对模式中的所有表进行逻辑复制。
功能概述
下图说明了模式发布的逻辑复制工作:
架构发布的逻辑复制

让我们逐步完成上图中的各个阶段:
1用户对表执行各种 DML 操作并执行准备/提交。
2后端进程会为用户执行的操作生成数据/WAL。
3后端向 WAL 发送者进程发送 SIGUSR1 信号,通知 WAL 记录可供处理。
4 walsender 进程开始对 WAL 记录进行逻辑解码 - pgoutput 插件转换从 WAL 读取的更改。
5 pgoutput 插件检查数据是否是模式发布的一部分。如果是,则使用流复制协议将数据连续传输到 Apply Worker。
6 Apply Worker 将数据映射到本地表,并在收到更改时以正确的事务顺序应用各个更改。
您可以在PostgreSQL git 存储库中查看实现的更多详细信息。
语法的变化
新语法允许在创建或更改发布时包括指定架构中的所有表。
CREATE PUBLICATION pub1 FOR ALL TABLES IN SCHEMA sch1,sch2;
或者
ALTER PUBLICATION pub1 ADD ALL TABLES IN SCHEMA sch3,sch4;
除了指定模式之外,新语法还允许在创建或更改发布时指定单个表。
CREATE PUBLICATION pub1 FOR ALL TABLES IN SCHEMA sch1,sch2, TABLE tbl1, tbl2;
或者
ALTER PUBLICATION pub1 ADD ALL TABLES IN SCHEMA sch3,sch4, TABLE tbl3, tbl4;
请注意,将模式添加到已订阅的发布将需要在订阅端执行ALTER SUBSCRIPTION … REFRESH PUBLICATION操作才能生效。
新系统表 pg_publication_namespace
将添加一个新的系统表 pg_publication_namespace,以维护用户为发布指定的模式。
用户可以使用 pg_publication_namespace 和 pg_publication 来获取与发布的模式映射,如下例所示。
postgres=# CREATE PUBLICATION pub1 FOR ALL TABLES IN SCHEMA sch1,sch2;
CREATE PUBLICATION
postgres=# SELECT pubname, pnnspid::regnamespace
postgres-# FROM pg_publication_namespace pn, pg_publication p
postgres-# WHERE pn.pnpubid = p.oid;
pubname | pnnspid
---------+---------
pub1 | sch1
pub1 | sch2
(2 rows)
对 pgoutput 的更改
修改了 pgoutput 插件以检查关系是否是模式发布的一部分并将更改发布给订阅者。
描述出版物
\d命令系列已更新为显示架构发布,而\dRp+变体现在将
显示与发布关联的架构。
postgres=# CREATE PUBLICATION pub1 FOR ALL TABLES IN SCHEMA sch1,sch2;
CREATE PUBLICATION
postgres=# \dRp+ pub1
Publication pub1
Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root
------+------------+---------+---------+---------+-----------+----------
Dba | f | t | t | t | t | f
Tables from schemas:
"sch1"
"sch2"
对 pg_dump 的更改
pg_dump 客户端工具已更新以识别是否创建发布以发布模式中的所有表并转储发布的 ddl,包括ALL TABLES IN SCHEMA选项。
pg_dump 生成的 DDL 示例:
--
-- Name: pub1; Type: PUBLICATION; Schema: -; Owner: dba
--
CREATE PUBLICATION pub1 WITH (publish = 'insert, update, delete, truncate');
ALTER PUBLICATION pub1 OWNER TO dba;
--
-- Name: pub1 sch1; Type: PUBLICATION TABLES IN SCHEMA; Schema: sch1; Owner: dba
--
ALTER PUBLICATION pub1 ADD ALL TABLES IN SCHEMA sch1;
--
-- Name: pub1 sch2; Type: PUBLICATION TABLES IN SCHEMA; Schema: sch2; Owner: dba
--
ALTER PUBLICATION pub1 ADD ALL TABLES IN SCHEMA sch2;
对 psql 的更改
psql 客户端工具已更新以支持ALL TABLES IN SCHEMA选项的制表符完成。
如何在 SCHEMA数据中发布所有表?
以下是使用新的ALL TABLES IN SCHEMA选项的步骤。
1在发布者和订阅者中创建一些模式和表:
postgres=# CREATE SCHEMA sch1;
CREATE SCHEMA
postgres=# CREATE TABLE sch1.tbl1 (col1 int);
CREATE TABLE
postgres=# CREATE TABLE sch1.tbl2 (col1 int);
CREATE TABLE
postgres=# CREATE SCHEMA sch2;
CREATE SCHEMA
postgres=# CREATE TABLE sch2.tbl3 (col1 int);
CREATE TABLE
postgres=# CREATE TABLE sch2.tbl4 (col1 int);
CREATE TABLE
2在发布者中创建发布:
postgres=# CREATE PUBLICATION pub1 FOR ALL TABLES IN SCHEMA sch1,sch2;
CREATE PUBLICATION
3通过指定发布者主机和发布者端口 6666 在订阅者中创建订阅:
postgres=# CREATE SUBSCRIPTION sub1 CONNECTION 'host=host1 dbname=postgres port=6666' PUBLICATION pub1;
NOTICE: created replication slot "sub1" on publisher
CREATE SUBSCRIPTION
4将一些数据插入发布者:
postgres=# INSERT INTO sch1.tbl1 VALUES(11);
INSERT 0 1
postgres=# INSERT INTO sch1.tbl2 VALUES(12);
INSERT 0 1
postgres=# INSERT INTO sch2.tbl3 VALUES(23);
INSERT 0 1
postgres=# INSERT INTO sch2.tbl4 VALUES(24);
INSERT 0 1
5检查发布者发布的数据是否在逻辑上复制到订阅者:
postgres=# SELECT * FROM sch1.tbl1;
col1
----
11
(1 rows)
postgres=# SELECT * FROM sch1.tbl2;
col1
----
12
(1 rows)
postgres=# SELECT * FROM sch2.tbl3;
col1
----
23
(1 rows)
postgres=# SELECT * FROM sch2.tbl4;
col1
----
24
(1 rows)
为未来
随着 PostgreSQL 15 中此功能的更改,我们现在拥有允许解码模式中存在的表的基础架构。下一步是在 PostgreSQL 的更高版本中实现对跳过模式中存在的少数表的支持。
文章来源:https://www.postgresql.fastware.com/blog/logical-replication-of-all-tables-in-schema-in-postgresql-15




