2025年9月25日: PostgreSQL 18 发布!
支持的版本: 当前 (18) / 17 / 16 / 15
开发版本: devel

29.5. 列列表 #

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

选择列可以基于行为或性能原因。但是,不要依赖此功能来实现安全:恶意的订阅者能够获取未专门发布的列中的数据。如果考虑安全性,可以在发布者端应用保护措施。

如果未指定列列表,则稍后添加到表中的任何列都会自动复制。这意味着具有命名所有列的列列表与根本没有列列表不同。

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

生成的列也可以在列列表中指定。这允许发布生成的列,而不管发布参数 publish_generated_columns。有关详细信息,请参阅 第 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)

提交更正

如果您在文档中看到任何不正确的内容、与您对特定功能的体验不符或需要进一步说明的内容,请使用 此表单 报告文档问题。