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

Описание:

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

У физической репликации есть один небольшой недостаток: синхронизируемые серверы должны иметь идентичную конфигурацию. Проще говоря, данные должны находиться в одних и тех же местах файловой системы. И еще одно – реплицируется любое изменение в файлах данных, даже если сами данные остаются прежними. К примеру, это происходит, когда на ведущем сервере выполняется команда VACUUM, которая удаляет из таблиц мертвые кортежи, или команда CLUSTER, которая реорганизует строки. Даже если над таблицей строится индекс, ведомому серверу передается не команда CREATE INDEX, а содержимое индексного файла. Это создает излишнюю нагрузку на сеть и может оказаться узким местом в достаточно нагруженной системе.

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

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

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

Подключение и настройка логической репликации

  1. Создадим в базе данных роль для репликации или включим репликацию для существующего пользователя:
postgres=# ALTER USER db_role REPLICATION; ALTER USER
  1. В файле pg_hba.conf разрешим этому пользователю подключаться к виртуальной базе данных replication:
host replication db_role 172.16.0.2/32 md5
  1. Присвоим конфигурационному параметру wal_level в файле postgresql.conf значение logical. Это необходимо, чтобы PostgreSQL записывал в WAL-файлы достаточно информации для репликации.
  2. Убедимся, что значение конфигурационного параметра max_replication_slots больше или равно количеству подписчиков, которые могут подключиться к серверу-издателю.
  3. Присвоим конфигурационному параметру max_wal_senders значение не меньше, чем у max_replication_slots.
  4. Создадим объект публикации. Публикация – это именованный набор таблиц. Если он создан, то сервер будет отслеживать изменения в этих таблицах и передавать их любому серверу, подписавшемуся на эту публикацию. Для этой цели используется команда CREATE PUBLICATION.

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

task07=> CREATE PUBLICATION task07 FOR ALL TABLES; CREATE PUBLICATION

На стороне подписчика следует создать подписку. Это специальный объект, описывающий подключение к существующей публикации издателя. Подписка создается командой CREATE SUBSCRIPTION, как показано в примере ниже:

task07=# CREATE SUBSCRIPTION task07 CONNECTION 'dbname=task07 host=publisher user=db_role' PUBLICATION task07;
CREATE SUBSCRIPTION

В этот момент на стороне публикатора в логи запишутся сообщения о том, что все таблицы, имеющиеся в базе task07, реплицируются подписчику.

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

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

Логическая репликация не распространяется на последовательности, на команды DDL и на команду TRUNCATE. Первичные ключи, ограничения UNIQUE и CHECK на конечных таблицах принимаются во внимание, но ограничения внешнего ключа игнорируются.

Логическую репликацию, как и потоковую, можно запустить в синхронном режиме. Для этого на стороне издателя нужно задать имя подписчика в конфигурационном параметре synchronous_standby_names в файле postgresql.conf, а на стороне подписчика прописать то же имя в строке соединения при выполнении команды CREATE SUBSCRIPTION.

Логическая репликация обладает следующими преимуществами, по сравнению с физической:

  1. она легко настраивается;
  2. ее можно настроить очень гибко:
  • не требуется, чтобы схемы базы данных на обоих серверах были идентичны, да и вообще серверы могут быть сконфигурированы по-разному;
  • один и тот же сервер может быть одновременно издателем и подписчиком;
  • одна и та же таблица может участвовать в нескольких подписках, так что в нее будут попадать данные с нескольких серверов;
  • публикацию можно настроить так, чтобы реплицировались только операции определенного типа (скажем, INSERT и DELETE, но не UPDATE);
  • конечная таблица на стороне подписчика доступна для записи;
  1. логическую репликацию теоретически можно использовать с разными основными версиями PostgreSQL;
  2. для нее не требуется стороннее программное обеспечение или оборудование, она включена в комплект поставки PostgreSQL;
  3. изменения данных, произведенные на физическом уровне (например, VACUUM или CLUSTER), не реплицируются.

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

  1. не принимаются во внимание внешние ключи, поэтому конечная база данных может оказаться в несогласованном состоянии;
  2. если на стороне издателя схема изменяется, так что нарушается совместимость со схемой на стороне подписчика, то репликация может внезапно перестать работать;
  3. подписчику реплицируются только изменения, произведенные в базе данных издателя. Если кто-то внесет изменения непосредственно в базу данных подписчика, то репликация не сможет восстановить синхронизацию таблиц;
  4. из всех объектов схемы реплицируются только таблицы. Это может стать проблемой, если в базах данных используются автоинкрементные поля на основе последовательностей.

Полезные ссылки:

Правила выполнения задания:

  1. Время создания окружения занимает до 5 минут.
  2. После нажатия кнопки «Начать выполнение» для вас будет создано окружение для выполнения задания, состоящее из одной или более виртуальнах машин с Ubuntu 18-04. К ним будут выданы IP, логин и пароль для доступа по SSH, а также при необходимости — дополнительных ресурсов.
  3. Также, если необходимо, вам могут быть выданы переменные, которые в задании указаны в фигурных скобках, — их надо будет подставить при выполнении задания (например, ${base_domain}).
  4. После выполнения всех пунктов задания нажмите кнопку «Проверить выполнение», и в течение 3-5 минут скрипт проверит выполнение всех условий и выставит вам оценку.
  5. В случае, если вы что-то забыли, можно исправить ошибку и отправить на проверку повторно (нажав кнопку «Проверить выполнение»).
  6. После получения удовлетворительной оценки нажмите кнопку «Завершить задание», чтобы созданное окружение уничтожилось и вы могли приступить к следующему заданию.
  7. Если у вас закончилось время (истек таймер) — окружение будет автоматически уничтожено и вам придется начать выполнение заново.
  8. Также, если вы успешно сдали задание, но у вас остались вопросы — вы всегда сможете задать их куратору после проверки (используя кнопку «Задать вопрос куратору») или в чате практикума в любое удобное для вас время. Обращаем внимание — кураторы проверяют вопросы в течение 24 часов.

Задание:

  1. На обоих серверах установить postgresql 11 через пакетный менеджер.

  2. На publisher:

  • Создать роль car_portal_app.
  • Разрешить безусловную аутентификацию клиентов в файле pg_hba.conf для роли из п.1 с подключением для любых адресов (0.0.0.0/0).
  • В файле postgresql.conf разрешить все имеющиеся IP-интерфейсы.
  • Присвоить конфигурационному параметру wal_level соответствующее значение для подписчика.
  • Перезапустить postgres.
  • Восстановить прилагаемую схему schema.sql пользователем postgres и дамп с базой данных data.sql под ролью car_portal_app из каталога /opt.
  • Добавить роль REPLICATION для роли (пользователя) car_portal_app.
  • Создать публикацию для восстановленной бд из дампа data.sql для всех таблиц.
  1. На subscriber:
  • Создать роль car_portal_app.
  • Разрешить безусловную аутентификацию клиентов в файле pg_hba.conf для роли из п.1 с подключением для любых адресов.
  • В файле postgresql.conf разрешить все имеющиеся IP-интерфейсы.
  • Перезапустить postgres.
  • Перенести с сервера publisher schema.sql в каталог /opt.
  • Восстановить схему schema.sql из каталога /opt.
  • На publisher найти восстановленную бд и создать подписку с именем car_portal на эту бд.
  1. На publisher:
  • Добавить запись в таблицу account для соответствующей схемы, которую прочтете в data.sql, содержащую first_name : Rebrain, last_name : me, email : info@rebrainme.com, password : md5('info@rebrainme.com'). После чего убедитесь, что информация попала на сервер subscriber.
  1. Если уверены, что все сделали правильно, отправляйте задание на проверку.

Связаться с нами