9.3 9.4 9.5 9.6 10 11 12 13 14 15
阿里云PostgreSQL 问题报告 纠错本页面

31.4. 列列表

31.4.1. 例子

每个发布可以选择性地指定每个表的哪些列被复制给订阅者。订阅者端的表必须至少包含所有发布的列。 如果未指定列列表,则发布者上的所有列都会被复制。 有关语法详细信息,请参见CREATE PUBLICATION

列的选择可以基于行为或性能原因。然而,不要依赖此功能来确保安全性: 恶意订阅者可以从未明确发布的列中获取数据。如果安全性是一个考虑因素, 可以在发布者端应用保护措施。

如果没有指定列列表,则后续添加的任何列都会自动复制。这意味着列出所有列的列列表 与根本没有列列表是不同的。

列表中只能包含简单的列引用。列表中列的顺序不会被保留。

当出版物同时发布SCHEMA中的表时,不支持指定列列表。

对于分区表,发布参数publish_via_partition_root确定使用哪个列列表。 如果publish_via_partition_roottrue,则使用根分区表的列列表。 否则,如果publish_via_partition_rootfalse(默认值), 则使用每个分区的列列表。

如果一个发布物发布UPDATEDELETE操作, 任何列清单必须包括表的复制标识列(参见REPLICA IDENTITY)。 如果一个发布物只发布INSERT操作,那么列清单可以省略复制标识列。

列表对TRUNCATE命令没有影响。

在初始数据同步期间,只复制已发布的列。然而,如果订阅者来自15之前的版本, 则在初始数据同步期间将复制表中的所有列,忽略任何列列表。

警告:合并来自多个出版物的列列表

目前不支持包含多个出版物的订阅,其中同一表已使用不同列列表发布。 CREATE SUBSCRIPTION 禁止创建这种订阅,但在创建订阅后, 仍然可以通过在出版物端添加或更改列列表来进入该情况。

这意味着更改已经订阅的出版物上的表格列列表可能会导致订阅方出现错误。

如果一个订阅受到这个问题的影响,恢复复制的唯一方法是调整出版方的一个列列表,使它们全部匹配; 然后要么重新创建订阅,要么使用ALTER SUBSCRIPTION ... DROP PUBLICATION来 删除一个有问题的出版物,然后再添加它。

31.4.1. 例子

创建一个表t1,用于以下示例。

test_pub=# 创建表 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
                 表 "public.t1"
 列    |  类型   | 校对   | 可空   | 默认值
--------+---------+-----------+----------+---------
 id     | integer |           | not null |
 a      | text    |           |          |
 b      | text    |           |          |
 c      | text    |           |          |
 d      | text    |           |          |
 e      | text    |           |          |
索引:
    "t1_pkey" 主键, btree (id)
发布:
    "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=# 从t1表按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 行)