通常,订阅端的表会与发布端表定义相同,因此如果发布端表包含 GENERATED 列, 订阅端表也会有对应的生成列。在这种情况下,始终使用订阅端表生成列的值。
例如,下面可以看到订阅端表的生成列值来自订阅端列自身的计算:
/* pub # */ CREATE TABLE tab_gen_to_gen (a int, b int GENERATED ALWAYS AS (a + 1) STORED); /* pub # */ INSERT INTO tab_gen_to_gen VALUES (1),(2),(3); /* pub # */ CREATE PUBLICATION pub1 FOR TABLE tab_gen_to_gen; /* pub # */ SELECT * FROM tab_gen_to_gen; a | b ---+--- 1 | 2 2 | 3 3 | 4 (3 rows) /* sub # */ CREATE TABLE tab_gen_to_gen (a int, b int GENERATED ALWAYS AS (a * 100) STORED); /* sub # */ CREATE SUBSCRIPTION sub1 CONNECTION 'dbname=test_pub' PUBLICATION pub1; /* sub # */ SELECT * from tab_gen_to_gen; a | b ---+---- 1 | 100 2 | 200 3 | 300 (3 rows)
实际上,在 18.0 之前的版本中,逻辑复制根本不会发布 GENERATED 列。
但在某些场景中,将生成列复制到普通列是有意义的。
当通过输出插件将数据复制到非 PostgreSQL 数据库时,此特性可能很有用, 尤其是目标数据库不支持生成列时。
默认不会发布生成列,但用户可以选择像普通列一样发布存储生成列。
有两种方式:
将 PUBLICATION 参数 publish_generated_columns 设置为 stored。 这样 PostgreSQL 逻辑复制会发布该发布中各表当前及未来的存储生成列。
指定表的 列列表, 显式指定要发布哪些存储生成列。
在确定发布哪些表列时,列列表优先级更高,会覆盖 publish_generated_columns 参数的效果。
下表汇总了逻辑复制涉及生成列时的行为,分别展示未启用和启用发布生成列时的结果。
Table 29.2. 复制结果汇总
| 发布生成列? | 发布端表列 | 订阅端表列 | 结果 |
|---|---|---|---|
| 否 | GENERATED | GENERATED | 发布端该列不复制。使用订阅端表生成列的值。 |
| 否 | GENERATED | 普通列 | 发布端该列不复制。使用订阅端普通列默认值。 |
| 否 | GENERATED | --missing-- | 发布端该列不复制。不会发生任何操作。 |
| 是 | GENERATED | GENERATED | 错误。不支持。 |
| 是 | GENERATED | 普通列 | 发布端该列值会复制到订阅端表列。 |
| 是 | GENERATED | --missing-- | 错误。该列会被报告为订阅端表缺失。 |
目前不支持一个订阅包含多个发布,且同一张表在这些发布中使用不同列列表。 见 Section 29.5。
如果同一订阅中一个发布对该表发布生成列,而另一个发布不发布生成列, 也会出现同样的问题。
如果订阅端版本早于 18,即使发布端定义了生成列,初始表同步也不会复制生成列。
如果您发现文档中有不正确的内容、与您使用特定功能的经验不符或需要进一步说明,请使用此表单来报告文档问题。