29.6. Репликация генерируемых столбцов #

Обычно таблица на стороне подписчика определена так же, как таблица публикующего узла, чтобы у подписчика был соответствующий генерируемый столбец, если в таблице публикующего узла есть столбец с предложением 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 столбцы с предложением GENERATED при логической репликации вообще не публикуются.

Однако иногда рекомендуется реплицировать генерируемый столбец в обычный.

Подсказка

Эта функциональность может быть полезна при репликации данных с помощью плагина в базу данных не на основе PostgreSQL, особенно если целевая база данных не поддерживает генерируемые столбцы.

По умолчанию генерируемые столбцы не публикуются, однако у пользователей есть возможность публиковать хранимые генерируемые столбцы так же, как и обычные.

Это можно сделать двумя способами:

  • Задайте значение stored для параметра publish_generated_columns команды CREATE PUBLICATION. Благодаря этому PostgreSQL будет публиковать текущие и будущие хранимые генерируемые столбцы таблиц публикации во время логической репликации.

  • Укажите список столбцов таблицы, чтобы явно задать, какие хранимые генерируемые столбцы нужно опубликовать.

    Примечание

    При определении того, какие столбцы таблицы нужно публиковать, приоритет будет у списка столбцов. Таким образом результат работы параметра publish_generated_columns будет перезаписан.

В следующей таблице обобщается поведение для сценариев, когда в логической репликации участвуют генерируемые столбцы. Результаты приведены для ситуации с выключенной и включённой публикацией генерируемых столбцов.

Таблица 29.2. Результаты репликации

Генерируемые столбцы публикуются?Столбец таблицы публикующего узлаСтолбец таблицы подписчикаРезультат
НетГенерируемыйГенерируемыйСтолбец таблицы публикующего узла не реплицируется. Используйте значение генерируемого столбца таблицы подписчика.
НетГенерируемыйОбычныйСтолбец таблицы публикующего узла не реплицируется. Используйте значение по умолчанию обычного столбца таблицы подписчика.
НетГенерируемый--Отсутствует--Столбец таблицы публикующего узла не реплицируется. Ничего не происходит.
ДаГенерируемыйГенерируемыйОшибка. Не поддерживается.
ДаГенерируемыйОбычныйЗначение столбца таблицы публикующего узла реплицируется на столбец таблицы подписчика.
ДаГенерируемый--Отсутствует--Ошибка. Столбец отсутствует в таблице подписчика.

Предупреждение

В настоящее время не поддерживаются подписки, связанные с несколькими публикациями, в которых одна таблица опубликована с разными списками столбцов. См. Раздел 29.5.

Такая же ситуация может возникать, если в одной публикации публикуются генерируемые столбы, а в другой публикации с той же подпиской генерируемые столбцы для той же таблицы не публикуются.

Примечание

Если на стороне подписчика используется версия ниже 18, то при первичной синхронизации таблиц генерируемые столбцы не копируются, даже если они определены на публикующем узле.

29.6. Generated Column Replication #

Typically, a table at the subscriber will be defined the same as the publisher table, so if the publisher table has a GENERATED column then the subscriber table will have a matching generated column. In this case, it is always the subscriber table generated column value that is used.

For example, note below that subscriber table generated column value comes from the subscriber column's calculation.

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

In fact, prior to version 18.0, logical replication does not publish GENERATED columns at all.

But, replicating a generated column to a regular column can sometimes be desirable.

Tip

This feature may be useful when replicating data to a non-PostgreSQL database via output plugin, especially if the target database does not support generated columns.

Generated columns are not published by default, but users can opt to publish stored generated columns just like regular ones.

There are two ways to do this:

  • Set the PUBLICATION parameter publish_generated_columns to stored. This instructs PostgreSQL logical replication to publish current and future stored generated columns of the publication's tables.

  • Specify a table column list to explicitly nominate which stored generated columns will be published.

    Note

    When determining which table columns will be published, a column list takes precedence, overriding the effect of the publish_generated_columns parameter.

The following table summarizes behavior when there are generated columns involved in the logical replication. Results are shown for when publishing generated columns is not enabled, and for when it is enabled.

Table 29.2. Replication Result Summary

Publish generated columns?Publisher table columnSubscriber table columnResult
NoGENERATEDGENERATEDPublisher table column is not replicated. Use the subscriber table generated column value.
NoGENERATEDregularPublisher table column is not replicated. Use the subscriber table regular column default value.
NoGENERATED--missing--Publisher table column is not replicated. Nothing happens.
YesGENERATEDGENERATEDERROR. Not supported.
YesGENERATEDregularPublisher table column value is replicated to the subscriber table column.
YesGENERATED--missing--ERROR. The column is reported as missing from the subscriber table.

Warning

There's currently no support for subscriptions comprising several publications where the same table has been published with different column lists. See Section 29.5.

This same situation can occur if one publication is publishing generated columns, while another publication in the same subscription is not publishing generated columns for the same table.

Note

If the subscriber is from a release prior to 18, then initial table synchronization won't copy generated columns even if they are defined in the publisher.

FAQ