受支持版本: 当前版本 (18) / 17 / 16 / 15
开发版本: devel

29.5. 列列表 #

每个发布都可以选择指定每个表中的哪些列复制到订阅端。订阅端上的表必须至少具有所有已发布的列。 如果未指定列列表,则会复制发布端上的所有列。有关语法的详细信息,见CREATE PUBLICATION

选择哪些列可以基于行为或性能方面的考虑。然而,不要依赖此功能来实现安全性: 恶意订阅端仍然可以获得未被明确发布的列中的数据。如果需要考虑安全性,应在发布端采取保护措施。

如果未指定列列表,那么以后向该表新增的任何列都会自动复制。这意味着,列出全部列的列列表与完全不指定列列表并不相同。

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

生成列也可以在列列表中指定。这样就可以不受发布参数 publish_generated_columns 的限制而发布生成列。详见 Section 29.6

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

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

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

列列表对TRUNCATE命令没有影响。

在初始数据同步期间,只会复制已发布的列。然而,如果订阅端使用的是 15 之 前的版本,那么在初始数据同步期间会复制表中的所有列,而忽略任何列列表。 如果订阅端使用的是 18 之前的版本,那么即使发布端定义了生成列,初始表同 步也不会复制生成列。

警告:组合来自多个发布的列列表

目前不支持这样的订阅:它包含多个发布,并且同一张表在这些发布中使用了不同的列列表。 CREATE SUBSCRIPTION会禁止创建这样的订阅,但在订阅创建之后, 仍然可能通过在发布端新增或修改列列表而进入这种情况。

这意味着,更改已被订阅的发布上表的列列表,可能会导致订阅端抛出错误。

如果某个订阅受到了这个问题的影响,那么恢复复制的唯一方法是调整发布端的某个列列表,使它们全部一致; 然后要么重新创建该订阅,要么使用ALTER SUBSCRIPTION ... DROP PUBLICATION 删除一个有问题的发布,再把它重新加回来。

29.5.1. 示例 #

创建一个表t1,供下面的示例使用。

/* pub # */ CREATE TABLE t1(id int, a text, b text, c text, d text, e text, PRIMARY KEY(id));

创建一个发布p1。为表t1定义一个列列表,以减少将被复制的列数。请注意,列列表中列名的顺序并不重要。

/* pub # */ CREATE PUBLICATION p1 FOR TABLE t1 (id, b, a, d);

psql可用于显示每个发布的列列表(如果已定义)。

/* pub # */ \dRp+
                                         Publication p1
  Owner   | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root
----------+------------+---------+---------+---------+-----------+-------------------+----------
 postgres | f          | t       | t       | t       | t         | none              | f
Tables:
    "public.t1" (id, a, b, d)

psql可用于显示每个表的列列表(如果已定义)。

/* 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

/* sub # */ CREATE TABLE t1(id int, b text, a text, d text, PRIMARY KEY(id));
/* sub # */ CREATE SUBSCRIPTION s1
/* sub - */ CONNECTION 'host=localhost dbname=test_pub application_name=s1'
/* sub - */ PUBLICATION p1;

在发布端节点上,向表t1插入一些行。

/* pub # */ INSERT INTO t1 VALUES(1, 'a-1', 'b-1', 'c-1', 'd-1', 'e-1');
/* pub # */ INSERT INTO t1 VALUES(2, 'a-2', 'b-2', 'c-2', 'd-2', 'e-2');
/* pub # */ INSERT INTO t1 VALUES(3, 'a-3', 'b-3', 'c-3', 'd-3', 'e-3');
/* 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的列列表中包含的数据会被复制。

/* 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)

提交更正

如果您发现文档中有不正确的内容、与您使用特定功能的经验不符或需要进一步说明,请使用此表单来报告文档问题。