31.4. Списки столбцов
Для каждой публикации можно дополнительно задать, какие столбцы каждой таблицы реплицируются для подписчиков. При этом в таблице на стороне подписчика должны быть как минимум все публикуемые столбцы. Если список столбов не задан, реплицируются все столбцы публикуемой таблицы. Подробнее синтаксис рассматривается в описании CREATE PUBLICATION.
Ограничение множества столбцов может быть продиктовано соображениями производительности или требованиями к поведению. Однако из соображений безопасности использовать это не следует: злоумышленник на стороне подписчика может получить данные из столбцов, которые не были опубликованы явно. Когда важно обеспечить безопасность, надо применять защиту на стороне публикации.
Если список столбцов не задан, все столбцы, добавляемые в таблицу позднее, будут реплицироваться автоматически. Это означает, что наличие списка, включающего все столбцы, не равнозначно отсутствию списка столбцов.
Список столбцов может содержать только простые ссылки на столбцы. Порядок столбцов в этом списке не сохраняется.
Указать список столбцов в публикации, которая также публикует все таблицы в схеме (FOR TABLES IN SCHEMA
), нельзя.
Для секционированных таблиц параметр публикации publish_via_partition_root
определяет, какой список столбцов использовать. Если publish_via_partition_root
имеет значение true
, используется список столбцов корневой секционированной таблицы. В противном случае, если publish_via_partition_root
имеет значение false
(по умолчанию), используется список столбцов каждой секции.
Если через публикацию реплицируются операции UPDATE
или DELETE
, список столбцов должен содержать столбцы, которые входят в идентификатор реплики для данной таблицы (см. REPLICA IDENTITY
). Если же через публикацию реплицируются только операции INSERT
, столбцы идентификатора реплики в списке столбцов могут отсутствовать.
Для команды TRUNCATE
списки столбцов не имеют значения.
Во время начальной синхронизации данных копируются только публикуемые столбцы. Однако если на стороне подписчика используется версия ниже 15, при начальной синхронизации копируются все столбцы в таблице, то есть любые списки столбцов игнорируются.
Внимание: объединение списков столбцов из нескольких публикаций
В настоящее время не поддерживаются подписки, связанные с несколькими публикациями, в которых одна таблица опубликована с разными списками столбцов. Команда CREATE SUBSCRIPTION не допускает создание таких подписок, но это всё равно может произойти при добавлении или изменении списков столбцов на стороне публикации после создания подписки.
Это означает, что изменение списков столбцов таблиц в публикациях, у которых уже есть подписчики, может привести к возникновению ошибок на стороне подписчика.
Если подписка затронута этой проблемой, единственный способ возобновить репликацию — изменить один из списков столбцов на стороне публикации, чтобы все они совпадали; а затем либо заново создать подписку, либо использовать ALTER SUBSCRIPTION ... DROP PUBLICATION
, чтобы удалить одну из проблемных публикаций и добавить её снова.
31.4.1. Примеры
Создайте таблицу t1
, которая будет использоваться в следующем примере.
test_pub=# CREATE TABLE t1(id int, a text, b text, c text, d text, e text, PRIMARY KEY(id)); CREATE TABLE
Создайте публикацию p1
, в которой для таблицы t1
определяется список столбцов, уменьшающий количество реплицируемых столбцов. Заметьте, что порядок имён столбцов в этом списке не имеет значения.
test_pub=# CREATE PUBLICATION p1 FOR TABLE t1 (id, b, a, d); CREATE PUBLICATION
Списки столбцов для каждой публикации можно просмотреть в psql
.
test_pub=# \dRp+ Publication p1 Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root ----------+------------+---------+---------+---------+-----------+---------- postgres | f | t | t | t | t | f Tables: "public.t1" (id, a, b, d)
Списки столбцов для каждой таблицы можно просмотреть в psql
.
test_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
.
test_sub=# CREATE TABLE t1(id int, b text, a text, d text, PRIMARY KEY(id)); CREATE TABLE test_sub=# CREATE SUBSCRIPTION s1 test_sub-# CONNECTION 'host=localhost dbname=test_pub application_name=s1' test_sub-# PUBLICATION p1; CREATE SUBSCRIPTION
Добавьте на стороне публикации в таблицу t1
несколько строк.
test_pub=# INSERT INTO t1 VALUES(1, 'a-1', 'b-1', 'c-1', 'd-1', 'e-1'); INSERT 0 1 test_pub=# INSERT INTO t1 VALUES(2, 'a-2', 'b-2', 'c-2', 'd-2', 'e-2'); INSERT 0 1 test_pub=# INSERT INTO t1 VALUES(3, 'a-3', 'b-3', 'c-3', 'd-3', 'e-3'); INSERT 0 1 test_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
.
test_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)
31.4. Column Lists
Each publication can optionally specify which columns of each table are replicated to subscribers. The table on the subscriber side must have at least all the columns that are published. If no column list is specified, then all columns on the publisher are replicated. See CREATE PUBLICATION for details on the syntax.
The choice of columns can be based on behavioral or performance reasons. However, do not rely on this feature for security: a malicious subscriber is able to obtain data from columns that are not specifically published. If security is a consideration, protections can be applied at the publisher side.
If no column list is specified, any columns added to the table later are automatically replicated. This means that having a column list which names all columns is not the same as having no column list at all.
A column list can contain only simple column references. The order of columns in the list is not preserved.
Specifying a column list when the publication also publishes FOR TABLES IN SCHEMA
is not supported.
For partitioned tables, the publication parameter publish_via_partition_root
determines which column list is used. If publish_via_partition_root
is true
, the root partitioned table's column list is used. Otherwise, if publish_via_partition_root
is false
(the default), each partition's column list is used.
If a publication publishes UPDATE
or DELETE
operations, any column list must include the table's replica identity columns (see REPLICA IDENTITY
). If a publication publishes only INSERT
operations, then the column list may omit replica identity columns.
Column lists have no effect for the TRUNCATE
command.
During initial data synchronization, only the published columns are copied. However, if the subscriber is from a release prior to 15, then all the columns in the table are copied during initial data synchronization, ignoring any column lists.
Warning: Combining Column Lists from Multiple Publications
There's currently no support for subscriptions comprising several publications where the same table has been published with different column lists. CREATE SUBSCRIPTION disallows creating such subscriptions, but it is still possible to get into that situation by adding or altering column lists on the publication side after a subscription has been created.
This means changing the column lists of tables on publications that are already subscribed could lead to errors being thrown on the subscriber side.
If a subscription is affected by this problem, the only way to resume replication is to adjust one of the column lists on the publication side so that they all match; and then either recreate the subscription, or use ALTER SUBSCRIPTION ... DROP PUBLICATION
to remove one of the offending publications and add it again.
31.4.1. Examples
Create a table t1
to be used in the following example.
test_pub=# CREATE TABLE t1(id int, a text, b text, c text, d text, e text, PRIMARY KEY(id)); CREATE TABLE
Create a publication p1
. A column list is defined for table t1
to reduce the number of columns that will be replicated. Notice that the order of column names in the column list does not matter.
test_pub=# CREATE PUBLICATION p1 FOR TABLE t1 (id, b, a, d); CREATE PUBLICATION
psql
can be used to show the column lists (if defined) for each publication.
test_pub=# \dRp+ Publication p1 Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root ----------+------------+---------+---------+---------+-----------+---------- postgres | f | t | t | t | t | f Tables: "public.t1" (id, a, b, d)
psql
can be used to show the column lists (if defined) for each table.
test_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)
On the subscriber node, create a table t1
which now only needs a subset of the columns that were on the publisher table t1
, and also create the subscription s1
that subscribes to the publication p1
.
test_sub=# CREATE TABLE t1(id int, b text, a text, d text, PRIMARY KEY(id)); CREATE TABLE test_sub=# CREATE SUBSCRIPTION s1 test_sub-# CONNECTION 'host=localhost dbname=test_pub application_name=s1' test_sub-# PUBLICATION p1; CREATE SUBSCRIPTION
On the publisher node, insert some rows to table t1
.
test_pub=# INSERT INTO t1 VALUES(1, 'a-1', 'b-1', 'c-1', 'd-1', 'e-1'); INSERT 0 1 test_pub=# INSERT INTO t1 VALUES(2, 'a-2', 'b-2', 'c-2', 'd-2', 'e-2'); INSERT 0 1 test_pub=# INSERT INTO t1 VALUES(3, 'a-3', 'b-3', 'c-3', 'd-3', 'e-3'); INSERT 0 1 test_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)
Only data from the column list of publication p1
is replicated.
test_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)