Перейти к основному содержимому

Уровень 2.0

Предусловие:

  • Изучена лекция 6 «Физическая репликация»

В этом задании вы узнаете:

  • О понятии логической репликации
  • Как устроена логическая репликация
  • Как настроить логическую репликацию

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

В предыдущей лекции рассмотрен механизм физической репликации данных, основанный на трансляции записей WAL от мастера к реплике.

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

Для управления логической репликацией предусмотрены специальные объекты базы данных: публикация и подписка, которые создаются SQL-командами CREATE PUBLICATION и CREATE SUBSCRIPTION соответственно.

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

По умолчанию изменения публикуются после фиксации транзакций.

Информация об изменениях в таблицах передается построчно с содержанием семантики изменений. При этом задействован тот же процесс, что и при потоковой репликации — wal sender. Однако, перед трансляцией записей WAL в этом случае процесс wal sender их декодирует в платформо-независимый вид. Поэтому двоичная совместимость серверов не требуется.

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

Для работы логической репликации публикующий экземпляр Pangolin должен иметь уровень журнала предзаписи logical (wal_level=logical). Уровня replica, используемого по умолчанию, в этом случае недостаточно.

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

Устройство логической репликации​

Как уже было сказано выше, трансляция изменений таблиц при логической репликации, как и при физической репликации, выполняется процессом wal sender.

При этом на стороне подписчика за прием и применение записей отвечает процесс logical replication worker.

Взаимодействие экземпляров осуществляется в соответствии с протоколом логической репликации.

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

Процесс wal sender читает записи WAL и группирует их в соответствии с активными транзакциями в своей локальной памяти.

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

Далее, процесс wal sender передает полученные декодированные записи экземпляру с подпиской. Выполняется это посредством слота логической репликации.

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

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

Транслируемые записи получает и применяет на подписчике процесс logical replication worker. За запуск процессов logical replication worker на подписчике отвечает фоновый процесс logical replication launcher.

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

Общее количество процессов wal_sender на экземпляре Pangolin ограничено значением параметра max_wal_senders, а общее количество слотов репликации — значением max_replication_slots.

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

В свою очередь на стороне подписки значение параметра max_logical_replication_workers, определяющего максимальное количество процессов logical replication worker, должно быть не меньше количества подписок.

Также на стороне подписки необходимо учитывать значение параметра max_worker_processes, определяющего общее количество всех рабочих процессов в экземпляре. Его значение должно быть как минимум на единицу больше значения max_logical_replication_workers, поскольку в нем учитывается также процесс logical replication launcher.

Настройка логической репликации​

Создание публикации​

Публикация — это именованный объект базы данных, определяющий набор изменений, который необходимо реплицировать.

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

Также не реплицируются команды DDL.

Как уже было сказано выше, для создания публикации используется SQL-команда CREATE PUBLICATION.

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

  • FOR TABLE — таблицы из заданного списка
  • FOR ALL TABLES — все таблицы в базе данных, включая те, которые будут созданы позже
  • FOR TABLES IN SCHEMA — все таблицы в заданном списке схем, включая таблицы, которые будут созданы позже

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

replication_db=# CREATE PUBLICATION some_pub FOR TABLE some_table;

При создании публикации можно выбрать операции, действия которых необходимо реплицировать. Для этого используется параметр publish в команде CREATE PUBLICATION, например:

replication_db=# CREATE PUBLICATION some_pub FOR TABLE some_table WITH (publish = 'insert, update');

Здесь будут публиковаться только изменения, выполненные операциями INSERT и UPDATE. Об удалении строк и очистке таблицы подписчики не узнают.

Информацию об имеющихся в базе данных публикациях можно получить с использованием метакоманды \dRp+ в psql, например:

replication_db=# \dRp+
Publication some_pub
Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root
----------+------------+---------+---------+---------+-----------+----------
postgres | f | t | t | f | f | f
Tables:
"public.some_table"

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

Создание подписки​

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

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

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

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

Создание подписки на публикацию выполняется командой CREATE SUBSCRIPTION, например:

replication_db=# CREATE SUBSCRIPTION some_sub
CONNECTION 'host={replica-IP} dbname=replication_db user=replicator password=replicator'
PUBLICATION some_pub;
NOTICE: created replication slot "some_sub" on publisher
CREATE SUBSCRIPTION

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

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

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

Сама команда CREATE SUBSCRIPTION может выполняться только суперпользователем.

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

Информацию об имеющихся подписках можно получить метакомандой \dRs в psql, например:

postgres=# \dRs
List of subscriptions
Name | Owner | Enabled | Publication
----------+----------+---------+-------------
some_sub | postgres | t | {some_pub}
(1 row)

Текущее состояние подписок можно узнать с использованием представления pg_stat_subscription.

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

Идентификация строк и конфликты​

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

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

Для указания способа идентификации используется команда ALTER TABLE ... REPLICA IDENTITY ..., выполняемая на стороне публикации. Может быть выбран один из следующих способов:

  • DEFAULT — идентификация по столбцам первичного ключа (используется по умолчанию для несистемных таблиц)
  • USING INDEX — идентификация по уникальному индексу со столбцами с ограничением NOT NULL
  • FULL — идентификация по всем столбцам таблицы, участвующим в публикации
  • NOTHING — запрет логической репликации для данной таблицы (используется по умолчанию для системных таблиц)

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

Если команда ALTER TABLE ... REPLICA IDENTITY ... выполнена при имеющихся подписках на таблицу, то соответствующие подписки должны быть пересозданы для получения актуальных метаданных о таблице, включающих способ идентификации.

Необходимо учитывать, что при идентификации по всем столбцам поиск строк в таблице на стороне подписки выполняется методом последовательного сканирования, что неэффективно для больших таблиц.

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

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

Также ошибки нарушения ограничения целостности фиксируются в журнале сообщений.

Статистику по количеству возникающих ошибок на подписке можно получить с использованием представления pg_stat_subscription_stats.

Частным случаем возникновения конфликтов является репликация одной и той же таблицы с одного экземпляра Pangolin на другой и обратно.

Изменение, выполненное на первом экземпляре, транслируется на второй и сразу обратно первому, который уже не может его применить из-за нарушения ограничений целостности.

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

Фильтрация строк и выбор столбцов​

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

replication_db=# CREATE PUBLICATION some_pub FOR TABLE some_table WHERE (id > 100);

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

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

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

replication_db=# CREATE PUBLICATION some_pub FOR TABLE some_table (id, value);

Триггеры на подписчике​

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

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

Однако, указанное поведение можно изменить.

Для этого на стороне публикации необходимо выполнить команду ALTER TABLE, а именно:

  • ALTER TABLE ... REPLICA TRIGGER ... — триггер будет срабатывать только на стороне подписки
  • ALTER TABLE ... ALWAYS TRIGGER ... — триггер будет срабатывать как на стороне публикации, так и на стороне подписки

При этом в триггерных функциях на стороне подписки с использованием параметра session_replication_role можно различать, в результате чего сработал триггер: применения реплицированной записи (session_replication_role=replica) или выполнения операции на экземпляре подписки (session_replication_role=origin).

Итоги​

Вы узнали, что:

  • В логической репликации используется модель «публикация-подписка»
  • Реплицируются изменения в таблицах
  • Возможен выбор таблиц и фильтрация изменений
  • Не требуется двоичная совместимость серверов

Самопроверка​

Вопрос 1

Изменения данных в каких объектах базы данных могут быть реплицированы с использованием логической репликации?

Вопрос 2

Операции каких SQL-команд могут быть реплицированы с использованием логической репликации? Выберите все правильные варианты:

Вопрос 3

Какие процессы задействованы на стороне подписчика в механизме логической репликации? Выберите все правильные варианты:

Вопрос 4

Какие способы идентификации строк на стороне подписчика могут использоваться? Выберите все правильные варианты: