每个发布可选地指定每张表的哪些列复制到订阅者。订阅者一侧的表至少必须具有所发布的所有列。如果未指定列列表,则发布者上的所有列都将被复制。有关语法的详细信息,请参见 CREATE PUBLICATION。
列选择可以基于行为或性能原因。不过,不要依赖此功能来保障安全性:恶意订阅者能够从未明确发布的列中获取数据。如果安全性受到关注,则保护措施可应用于发布者一侧。
如果未指定列列表,则稍后添加到表的任何列都会自动复制。这意味着拥有指定所有列的列列表与根本不设置列列表不同。
列列表只能包含简单的列引用。列表中列的顺序不会保留。
当发布时还发布 FOR TABLES IN SCHEMA
时,指定列列表不受支持。
对于分区表,发布参数 publish_via_partition_root
确定要使用哪个列列表。如果 publish_via_partition_root
是 true
,则使用根分区表的列列表。否则,如果 publish_via_partition_root
是 false
(默认值),则使用每个分区的列列表。
如果一个发布刊登中发布UPDATE
或DELETE
操作,任何列列表必须包含表副本标识列(参见REPLICA IDENTITY
)。如果一个发布刊登仅发布INSERT
操作,列列表可以忽略副本标识列。
列列表对TRUNCATE
命令没有影响。
在初始数据同步过程中,只复制发布的列。然而,如果订户来自版本 15 之前,则所有列表中的列都会在初始数据同步时复制,并忽略所有列列表。
目前不支持将相同表以不同列列表发布的数条发布刊登包括在内的订用关系。CREATE SUBSCRIPTION不允许创建此类订用关系,但通过在创建了订用关系后,在发布刊登侧添加或更改列列表,仍然可能进入该情况。
这意味着更改已订阅发布刊登上的表的列列表可能导致在订户侧引发错误。
如果一个订用关系受到该问题影响,恢复复制的唯一方法是调整发布刊登側的一个列列表,使其全部匹配;然后,重新创建订用关系,或使用ALTER SUBSCRIPTION ... DROP PUBLICATION
删除出错的一个发布刊登并重新添加。
创建表t1
作为以下示例中使用。
test_pub=# CREATE TABLE t1(id int, a text, b text, c text, d text, e text, PRIMARY KEY(id)); CREATE TABLE
创建发布刊登p1
。为表t1
定义列列表,以减少将复制的列的数量。请注意,列列表中列名称的顺序不重要。
test_pub=# CREATE PUBLICATION p1 FOR TABLE t1 (id, b, a, d); CREATE PUBLICATION
psql
可用于为每个发布刊登显示列列表(如果已定义)。
test_pub=# \dRp+ Publication p1 Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root ----------+------------+---------+---------+---------+-----------+---------- postgres | f | t | t | t | t | f Tables: "public.t1" (id, a, b, d)
psql
可用于为每个表显示列列表(如果已定义)。
test_pub=# \d t1 Table "public.t1" Column | Type | Collation | Nullable | Default --------+---------+-----------+----------+--------- id | integer | | not null | a | text | | | b | text | | | c | text | | | d | text | | | e | text | | | Indexes: "t1_pkey" PRIMARY KEY, btree (id) Publications: "p1" (id, a, b, d)
在订户节点上,创建表t1
,现在它仅需要发布者表t1
的部分列,并创建订阅s1
,订阅发布刊登p1
。
test_sub=# CREATE TABLE t1(id int, b text, a text, d text, PRIMARY KEY(id)); CREATE TABLE test_sub=# CREATE SUBSCRIPTION s1 test_sub-# CONNECTION 'host=localhost dbname=test_pub application_name=s1' test_sub-# PUBLICATION p1; CREATE SUBSCRIPTION
在发布者节点上,向表t1
插入一些行。
test_pub=# INSERT INTO t1 VALUES(1, 'a-1', 'b-1', 'c-1', 'd-1', 'e-1'); INSERT 0 1 test_pub=# INSERT INTO t1 VALUES(2, 'a-2', 'b-2', 'c-2', 'd-2', 'e-2'); INSERT 0 1 test_pub=# INSERT INTO t1 VALUES(3, 'a-3', 'b-3', 'c-3', 'd-3', 'e-3'); INSERT 0 1 test_pub=# SELECT * FROM t1 ORDER BY id; id | a | b | c | d | e ----+-----+-----+-----+-----+----- 1 | a-1 | b-1 | c-1 | d-1 | e-1 2 | a-2 | b-2 | c-2 | d-2 | e-2 3 | a-3 | b-3 | c-3 | d-3 | e-3 (3 rows)
仅来自发布刊登p1
的列列表的数据会复制。
test_sub=# SELECT * FROM t1 ORDER BY id; id | b | a | d ----+-----+-----+----- 1 | b-1 | a-1 | d-1 2 | b-2 | a-2 | d-2 3 | b-3 | a-3 | d-3 (3 rows)