每个发布可以选择性地指定每个表的哪些列被复制给订阅者。订阅者端的表必须至少包含所有发布的列。 如果未指定列列表,则发布者上的所有列都会被复制。 有关语法详细信息,请参见CREATE PUBLICATION。
列的选择可以基于行为或性能原因。然而,不要依赖此功能来确保安全性: 恶意订阅者可以从未明确发布的列中获取数据。如果安全性是一个考虑因素, 可以在发布者端应用保护措施。
如果没有指定列列表,则后续添加的任何列都会自动复制。这意味着列出所有列的列列表 与根本没有列列表是不同的。
列表中只能包含简单的列引用。列表中列的顺序不会被保留。
当publication同时发布SCHEMA中的表
时,不支持指定列列表。
对于分区表,发布参数publish_via_partition_root
确定使用哪个列列表。
如果publish_via_partition_root
为true
,则使用根分区表的列列表。
否则,如果publish_via_partition_root
为false
(默认值),
则使用每个分区的列列表。
如果一个publication发布UPDATE
或DELETE
操作,
任何列清单必须包括表的复制标识列(参见REPLICA IDENTITY
)。
如果一个publication只发布INSERT
操作,那么列清单可以省略复制标识列。
列表对TRUNCATE
命令没有影响。
在初始数据同步期间,只复制已发布的列。然而,如果订阅者来自15之前的版本, 则在初始数据同步期间将复制表中的所有列,忽略任何列列表。
目前不支持包含多个publication的订阅,其中同一表已使用不同列列表发布。 CREATE SUBSCRIPTION 禁止创建这种订阅,但在创建订阅后, 仍然可以通过在publication端添加或更改列列表来进入该情况。
这意味着更改已经订阅的publication上的表格列列表可能会导致订阅方出现错误。
如果一个订阅受到这个问题的影响,恢复复制的唯一方法是调整出版方的一个列列表,使它们全部匹配;
然后要么重新创建订阅,要么使用ALTER SUBSCRIPTION ... DROP PUBLICATION
来
删除一个有问题的publication,然后再添加它。
创建一个表t1
,用于以下示例。
test_pub=# CREATE TABLE t1(id int, a text, b text, c text, d text, e text, PRIMARY KEY(id)); CREATE TABLE
创建一个publicationp1
。为表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)
只有来自publicationp1
的列列表数据被复制。
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)