29.5. 列列表

每个发布都可以选择指定各表中哪些列需要复制给订阅端。订阅端的表至少必须包含发布的所有列。如果未指定列列表,就会复制发布端的所有列。语法详见 CREATE PUBLICATION。 CREATE PUBLICATION

选择列可以出于行为或性能方面的考虑。不过,不要将这个功能作为安全措施:恶意订阅端能够获取未被明确发布的列的数据。如果需要安全保护,应在发布端实施。

如果未指定列列表,之后添加到表中的列也会自动复制。因此,列出全部现有列的列表,与完全不指定列列表并不相同。

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

生成列也可以写入列列表。这样,无论发布参数 publish_generated_columns 如何设置,都可以发布这些生成列。详情参见第 29.6 节。 publish_generated_columns Section 29.6

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

对于分区表,发布参数 publish_via_partition_root 决定使用哪个列列表。值为 true 时,使用根分区表的列表;值为 false(默认值)时,分别使用各分区自己的列表。 publish_via_partition_root

如果发布包含 UPDATE 或 DELETE 操作,任何列列表都必须包含表的副本标识列,参见 REPLICA IDENTITY。若只发布 INSERT 操作,则可以省略副本标识列。 REPLICA IDENTITY

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

初始数据同步只复制已发布的列。但是,订阅端版本早于 15 时,初始同步会忽略列列表,复制表中的所有列。订阅端版本早于 18 时,即便发布端定义了生成列,初始表同步也不会复制这些生成列。

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

目前不支持这样的订阅:订阅多个发布,而同一张表在这些发布中使用不同的列列表。CREATE SUBSCRIPTION 会阻止创建这种订阅,但订阅创建后,在发布端新增或修改列列表,仍可能造成这种情况。 CREATE SUBSCRIPTION

因此,修改已经有订阅者的发布中某张表的列列表,可能导致订阅端报错。

受此问题影响时,恢复复制的唯一办法是调整发布端的列列表,使它们全部一致;随后重新创建订阅,或者用 ALTER SUBSCRIPTION … DROP PUBLICATION 移除一个有问题的发布,再重新添加它。 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)
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容