PostgreSQL 中文参考文档
🌐 英文原版 官方 ↗

CREATE PUBLICATION

CREATE PUBLICATION — 定义一个新的发布

Synopsis

CREATE PUBLICATION name
    [ FOR ALL TABLES
      | FOR publication_object [, ... ] ]
    [ WITH ( publication_parameter [= value] [, ... ] ) ]

where publication_object is one of:

    TABLE table_and_columns [, ... ]
    TABLES IN SCHEMA { schema_name | CURRENT_SCHEMA } [, ... ]

and table_and_columns is:

    [ ONLY ] table_name [ * ] [ ( column_name [, ... ] ) ] [ WHERE ( expression ) ]

描述

CREATE PUBLICATION 向当前数据库中添加一个新的发布。发布名称必须与当前数据库中任何现有发布的名称不同。

发布本质上是一组表,这些表的数据更改将通过逻辑复制被复制。有关发布如何融入逻辑复制设置的详细信息,请参见 Section 29.1。

参数

name #

新发布的名称。

FOR TABLE #

指定要加入到发布中的表的列表。如果在表名之前指定了 ONLY,则只有该表会被加入到发布中。如果没有指定 ONLY,则该表及其所有子表(如果有)都会被加入。还可以在表名之后指定 *,以显式表明包含子表。不过,这并不适用于分区表。分区表的分区总是被隐式地视为发布的一部分,因此它们永远不会被显式地加入到发布中。

如果指定了可选的 WHERE 子句,它会定义一个 行过滤器 表达式。expression 求值为假或空的行将不会被发布。注意,表达式两边必须加上圆括号。它对 TRUNCATE 命令没有影响。

当指定了列列表时,只有被列出的列会被复制。列列表也可以包含存储生成列。如果省略了列列表,发布默认会复制所有非生成列(包括将来添加的任何列)。如果 publish_generated_columns 被设置为 stored,存储生成列也可以被复制。指定列列表对 TRUNCATE 命令没有影响。有关列列表的详细信息,请参见 Section 29.5。

只有持久的基表和分区表才能成为发布的一部分。临时表、非日志表、外部表、物化视图和普通视图不能成为发布的一部分。

当发布同时发布 FOR TABLES IN SCHEMA 时,不支持指定列列表。

当一个分区表被加入到一个发布中时,它所有的现有分区和未来分区都会被隐式地视为该发布的一部分。因此,即使是直接在某个分区上执行的操作,也会通过其祖先所属的发布被发布。

FOR ALL TABLES #

将该发布标记为复制数据库中所有表的更改(包括将来创建的表)的发布。

FOR TABLES IN SCHEMA #

将该发布标记为复制指定模式列表中所有表的更改(包括将来创建的表)的发布。

当发布同时发布带有列列表的表时,不支持指定模式。

只有该模式中存在的持久基表和分区表才会被包含为发布的一部分。来自该模式的临时表、非日志表、外部表、物化视图和普通视图不会成为发布的一部分。

当一个分区表通过模式级发布进行发布时,它所有的现有分区和未来分区都会被隐式地视为该发布的一部分,无论它们是否来自发布的模式。因此,即使是直接在某个分区上执行的操作,也会通过其祖先所属的发布被发布。

WITH ( publication_parameter [= value] [, ... ] ) #

该子句为发布指定可选参数。支持以下参数:

publish (string) #

该参数决定新发布将向订阅者发布哪些 DML 操作。值是一个以逗号分隔的操作列表。允许的操作有 insert、update、delete 和 truncate。默认发布所有动作,因此该选项的默认值为 'insert, update, delete, truncate'。

该参数只影响 DML 操作。特别是,逻辑复制的初始数据同步(参见 Section 29.9.1)在复制现有表数据时不会考虑该参数。

publish_generated_columns (enum) #

指定是否复制与发布相关联的表中存在的生成列。可能的值为 none 和 stored。

默认值为 none,这意味着与发布相关联的表中存在的生成列将不会被复制。

如果设置为 stored,则与发布相关联的表中存在的存储生成列将被复制。

Note

如果订阅者来自 18 之前的发行版,那么即使发布者端的参数 publish_generated_columns 为 stored,初始表同步也不会复制生成列。

有关生成列逻辑复制的更多细节,请参见 Section 29.6。

publish_via_partition_root (boolean) #

该参数控制对分区表(或其任何分区)的更改如何被发布。当设置为 true 时,更改将使用根分区表的身份和模式来发布。当设置为 false(默认值)时,更改将使用实际发生更改的各个分区的身份和模式来发布。启用该选项后,更改可以被复制到一个非分区表,或者复制到一个分区结构与发布者不同的分区表。

可能存在一个订阅组合了多个发布的情况。如果某个分区表由任何一个设置了 publish_via_partition_root = true 的被订阅发布进行发布,那么对该分区表(或其分区)的更改将使用该分区表的身份和模式来发布,而不是使用各个分区的身份和模式。

该参数还会影响如何为分区选择行过滤器和列列表;详细内容见下文。

如果启用了此项,直接在分区上执行的 TRUNCATE 操作将不会被复制。

当指定 boolean 类型的参数时,= value 部分可以被省略,这等价于指定 TRUE。

注记

如果没有指定 FOR TABLE、FOR ALL TABLES 或 FOR TABLES IN SCHEMA,那么发布一开始的表集合为空。如果以后要添加表或模式,这会很有用。

创建发布并不会开始复制。它只是为未来的订阅者定义分组和过滤逻辑。

要创建发布,调用用户必须拥有当前数据库的 CREATE 特权。(当然,超级用户会绕过这一检查。)

要将一个表添加到发布中,调用用户必须拥有该表的所有权。FOR ALL TABLES 和 FOR TABLES IN SCHEMA 子句要求调用用户是超级用户。

加入到发布 UPDATE 和/或 DELETE 操作的发布中的表必须定义 REPLICA IDENTITY(副本标识)。否则,这些操作在这些表上将不被允许。

任何列列表都必须包含 REPLICA IDENTITY 列,这样 UPDATE 或 DELETE 操作才能被发布。如果发布只发布 INSERT 操作,则没有列列表限制。

行过滤器表达式(即 WHERE 子句)必须只包含被 REPLICA IDENTITY 覆盖的列,这样 UPDATE 和 DELETE 操作才能被发布。对于 INSERT 操作的发布,WHERE 表达式中可以使用任何列。行过滤器允许不包含用户定义函数、用户定义操作符、用户定义类型、用户定义排序规则、非不可变内建函数或系统列引用的简单表达式。

属于 REPLICA IDENTITY 一部分的生成列必须被显式发布,方法是将它们列在列列表中或者启用 publish_generated_columns 选项,这样 UPDATE 和 DELETE 操作才能被发布。

如果指定了 FOR TABLES IN SCHEMA 并且该表属于被引用的模式,那么该表上的行过滤器就变得多余了。

对于被发布的分区表,如果发布参数 publish_via_partition_root 为真,则每个分区的行过滤器取自被发布的分区表;如果为假(默认值),则取自分区本身。有关行过滤器的详细信息,请参见 Section 29.4。类似地,对于被发布的分区表,如果发布参数 publish_via_partition_root 为真,则每个分区的列列表取自被发布的分区表;如果为假,则取自分区本身。

对于 INSERT ... ON CONFLICT 命令,发布将发布由该命令产生的操作。根据其结果,它可能作为 INSERT 或 UPDATE 被发布,也可能根本不被发布。

对于 MERGE 命令,发布将为每个被插入、更新或删除的行发布一个 INSERT、UPDATE 或 DELETE。

将一个表 ATTACH 到一棵根由发布进行发布、且 publish_via_partition_root 设置为 true 的分区树中,并不会导致该表已有的内容被复制。

COPY ... FROM 命令会作为 INSERT 操作被发布。

DDL 操作不会被发布。

WHERE 子句表达式会以用于复制连接的角色来执行。

示例

创建一个发布,发布两个表中的所有更改:

CREATE PUBLICATION mypublication FOR TABLE users, departments;

创建一个发布,发布活动部门的所有更改:

CREATE PUBLICATION active_departments FOR TABLE departments WHERE (active IS TRUE);

创建一个发布,发布所有表中的所有更改:

CREATE PUBLICATION alltables FOR ALL TABLES;

创建一个发布,只发布一个表中的 INSERT 操作:

CREATE PUBLICATION insert_only FOR TABLE mydata
    WITH (publish = 'insert');

创建一个发布,发布表 users、departments 的所有更改,以及模式 production 中所有表的所有更改:

CREATE PUBLICATION production_publication FOR TABLE users, departments, TABLES IN SCHEMA production;

创建一个发布,发布模式 marketing 和 sales 中所有表的所有更改:

CREATE PUBLICATION sales_publication FOR TABLES IN SCHEMA marketing, sales;

创建一个发布,发布表 users 的所有更改,但只复制列 user_id 和 firstname:

CREATE PUBLICATION users_filtered FOR TABLE users (user_id, firstname);

兼容性

CREATE PUBLICATION 是 PostgreSQL 的扩展。

另请参阅

ALTER PUBLICATION, DROP PUBLICATION, CREATE SUBSCRIPTION, ALTER SUBSCRIPTION