Логическая репликация

Обзор

Логическая репликация — это метод репликации объектов данных и их изменений, использующий репликационные идентификаторы (обычно это первичный ключ). Термин "логическая репликация" используется, чтобы отличать такую репликацию от физической, которая построена на адресах блоков и побайтовом копировании. Логическая репликация позволяет контролировать не только репликацию данных, но и аспекты безопасности.

Логическая репликация использует модель публикаций/подписок (publish/subscribe) с одним или несколькими подписчиками (subscribers), которые подписываются на одну или несколько публикаций (publications) на ноде публикации (publishing node). Подписчики получают данные из публикаций и могут повторно публиковать данные для каскадной репликации или более сложных конфигураций репликации.

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

Типичные сценарии использования логической репликации:

  • передача подписчикам инкрементальных изменений в одной базе данных или подмножестве базы данных;

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

  • объединение нескольких баз данных в одну, например, для целей анализа;

  • репликация данных между разными мажорными версиями PostgreSQL;

  • репликация данных между экземплярами PostgreSQL на разных платформах;

  • предоставление доступа к реплицированным данным различным группам пользователей;

  • совместное использование данных в нескольких базах данных.

БД-подписчик ведет себя так же, как и любой другой экземпляр PostgreSQL, и может быть публикатором, если создать в ней публикации. Когда подписчик действует как приложение с доступом только на чтения, конфликтов не возникает. Если какие-либо приложения или другие подписчики пишут в один и тот же набор таблиц, могут возникнуть конфликты.

Для получения подробной информации об ограничениях логической репликации обратитесь к статье Restrictions.

Чтобы настроить логическую репликацию, выполните следующие действия:

Параметры конфигурации

Логическая репликация требует установки нескольких параметров конфигурации. Используйте раздел postgresql.conf custom section на вкладке Clusters → Кластер ADPG → Services → ADPG → Primary configuration пользовательского интерфейса ADCM, чтобы указать эти параметры. Получить дополнительную информацию по настройке параметров можно в статье Конфигурационные параметры.

Установите следующие параметры на ноде публикации:

  • Параметр wal_level должен иметь значение logical.

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

  • Параметр max_wal_senders должен быть не меньше чем max_replication_slots плюс количество физических реплик, подключаемых одновременно.

 

На ноде подписчика необходимо указать параметры, перечисленные ниже:

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

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

  • max_worker_processes должен включать дополнительные рабочие процессы для репликации, как минимум max_logical_replication_workers плюс 1. Обратите внимание, что некоторые расширения и параллельные запросы занимают слоты из числа max_worker_processes. В отличие от остальных параметров, вы можете установить значение max_worker_processes в разделе ADPG configurations на вкладке Primary configuration. За дополнительной информацией обратитесь к статье Конфигурационные параметры.

Также необходимо проверить, не препятствуют ли репликации параметры, указанные в разделе PG_HBA на вкладке Clusters → Кластер ADPG → Services → ADPG → Primary configuration пользовательского интерфейса ADCM. Эти настройки зависят от конфигурации вашей сети и пользователя, от имени которого будет осуществляться подключение.

Публикация

Публикация может быть определена на любом ведущем физическом сервере репликации. Сервер, содержащий публикацию, называется публикующим (publisher). Публикация — это набор изменений, сгенерированный из таблицы или группы таблиц. Она также может называется набором репликации (replication set). Каждая публикация существует только в одной базе данных.

Публикации отличаются от схем и не влияют на доступ к таблице. Каждую таблицу можно включить в несколько публикаций. В настоящее время публикации могут содержать только таблицы. Объекты должны быть добавлены к ним явно, если только публикация не создается для всех таблиц с модификатором ALL TABLES.

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

Чтобы реплицировать операции UPDATE и DELETE, опубликованная таблица должна иметь идентификатор реплики (replica identity). Идентификатор реплики позволяет найти соответствующие строки для их обновления или удаления на стороне подписчика. По умолчанию первичный ключ является идентификатором реплики. Можно указать другой уникальный идентификатор для реплики. Если в таблице нет подходящего ключа, в качестве ключа можно использовать всю строку целиком. Для этого укажите значение идентификатора реплики full. Однако такой подход очень неэффективен и его следует использовать, если нет другого решения. Если на стороне публикующей ноды выбран идентификатор, отличный от full, идентификатор, состоящий из такого же или меньшего количества столбцов, также должен быть определен на стороне подписчика. За дополнительными сведениями о назначении идентификатора реплики обратитесь к статье REPLICA IDENTITY. Если таблица без идентификатора реплики добавляется к публикации, которая реплицирует операции UPDATE или DELETE, эти операции вызовут ошибку на ноде публикации. Операции INSERT могут быть обработаны без указания идентификатора реплики.

У каждой публикации может быть несколько подписчиков.

Используйте команду CREATE PUBLICATION, чтобы создать публикацию. Следующая команда создает публикацию, которая публикует все изменения в таблицах books и orders:

CREATE PUBLICATION publication1 FOR TABLE books, orders;

Код ниже создает публикацию, которая публикует все изменения во всех таблицах:

CREATE PUBLICATION all_tables FOR ALL TABLES;

Следующая публикация публикует операции DELETE, выполненные в таблице books:

CREATE PUBLICATION delete_publication FOR TABLE books WITH (publish = 'delete');

Вы можете использовать команду ALTER PUBLICATION, чтобы изменить определение публикации.

Приведенная ниже команда изменяет публикацию delete_publication, чтобы она публиковала не только удаления, но и обновления:

ALTER PUBLICATION delete_publication SET (publish = 'update, delete');

Код ниже добавляет таблицу authors в publication1:

ALTER PUBLICATION publication1 ADD TABLE authors;

Операции ADD TABLE и DROP TABLE являются транзакционными. Таким образом, репликация таблицы будет начата или закончена только после фиксации транзакции.

Чтобы удалить публикацию, вызовите команду DROP PUBLICATION:

DROP PUBLICATION all_tables;

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

SELECT * FROM pg_publication;

SELECT * FROM pg_publication_tables;

Подписка

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

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

У подписчика может быть несколько подписок. Можно определить несколько подписок между одной парой нода публикации/подписчик. При этом необходимо следить за тем, чтобы объекты публикации не пересекались.

Каждая подписка получает изменения через один слот репликации. Для начальной синхронизации данных могут потребоваться дополнительные слоты репликации. Они удаляются после завершения синхронизации данных. За дополнительной информацией обратитесь к статье Replication slot management.

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

Подписки могут быть заархивированны во время создания дамп-файла базы данных. Утилита pg_dump добавляет подписки в файл SQL dump, если она запускается от имени суперпользователя. В противном случае подписки пропускаются, так как пользователи без прав суперпользователя не могут прочитать информацию о подписке из каталога pg_subscription.

Используйте команду CREATE SUBSCRIPTION, чтобы добавить подписку:

CREATE SUBSCRIPTION subscription1
CONNECTION 'host=10.92.6.36 port=5432 user=postgres dbname=book_store password=postgres'
PUBLICATION publication1, delete_publication;

Используйте команду ALTER SUBSCRIPTION, чтобы изменить подписку. Следующий код изменяет subscription1, делая её подписанной на публикацию all_tables:

ALTER SUBSCRIPTION subscription1 SET PUBLICATION all_tables;

Команда ниже отключает (останавливает) подписку:

ALTER SUBSCRIPTION subscription1 DISABLE;

Чтобы удалить подписку, используйте DROP SUBSCRIPTION:

DROP SUBSCRIPTION subscription1;

При удалении и повторном создании подписки информация о синхронизации теряется. Вам необходимо повторно синхронизировать данные после воссоздания подписки.

Только таблицы могут быть целью репликации. Например, вы не можете реплицировать данные в представление (view).

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

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

Конфликты

Логическая репликация ведет себя аналогично операциям DML: данные обновляются, даже если они были изменены локально на ноде подписчика. Если входящие данные нарушают какие-либо ограничения, репликация останавливается. Это считается конфликтом.

Конфликт вызывает ошибку и останавливает репликацию. Необходимо разрешить конфликт вручную. Подробности о конфликте можно найти в журнале сервера подписчика (subscriber server log). Путь по умолчанию — /pg_data1/adpg14/log.

Пример:

2023-01-26 17:29:06.242 UTC [14525] LOG:  background worker "logical replication worker" (PID 1389) exited with exit code 1
2023-01-26 17:29:06.274 UTC [1390] ERROR:  duplicate key value violates unique constraint "test1_pkey"
2023-01-26 17:29:06.274 UTC [1390] DETAIL:  Key (employee_id)=(1) already exists.
2023-01-26 17:29:06.274 UTC [1390] CONTEXT:  COPY test1, line 1

Разрешение конфликта может заключаться либо в изменении данных на стороне подписчика, чтобы они не конфликтовали с приходящим изменением, либо в пропуске транзакции, конфликтующей с существующими данными. Пропустить транзакцию можно, вызвав функцию pg_replication_origin_advance, которой передаётся соответствующее имя подписки, а также позиция в качестве параметров. Текущую позицию источников можно найти в системном представлении pg_replication_origin_status.

При репликации операций UPDATE или DELETE отсутствие данных не вызывает конфликта, так что такие операции просто пропускаются.

Безопасность

Пользователь, имеющий право изменения схемы таблиц на стороне подписчика, может выполнить произвольный код как суперпользователь. Ограничьте круг владельцев и ролей, имеющих право TRIGGER для таких таблиц, доверенными ролями. Кроме того, если ненадежные пользователи могут создавать таблицы, используйте публикации, которые явно перечисляют таблицы. Создавайте подписку FOR ALL TABLES, только когда доверяете всем пользователям, имеющим право создавать таблицы на стороне публикации или подписки.

Роль, используемая для подключения репликации, должна иметь атрибут REPLICATION или быть суперпользователем. Если у роли нет атрибутов SUPERUSER и BYPASSRLS, при репликации могут выполняться политики защиты строк, определённые на стороне публикации. Если эта роль не может доверять владельцам всех таблиц, добавьте в строку подключения options=-crow_security=off;. Если владелец таблицы добавит политику защиты строк позже, при таком значении параметра репликация остановится, но политика выполняться не будет. Используйте раздел PG_HBA на вкладке Clusters → Кластер ADPG → Services → ADPG → Primary configuration пользовательского интерфейса ADCM, чтобы настроить доступ для роли. Роль для репликации должна иметь атрибут LOGIN.

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

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

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

Создавать подписки разрешено только суперпользователям.

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

Нашли ошибку? Выделите текст и нажмите Ctrl+Enter чтобы сообщить о ней