Недавно один из наших клиентов обратился к нам с одной интересной задачей: ему нужно было перенести весь свой кластер PostgreSQL с DBaaS (Database as a Service) на дроплет в рамках DigitalOcean. Причиной их перехода с DBaaS на дроплеты была их более низкая стоимость. Эта задача оказалась довольно сложной, поскольку в документации DigitalOcean четко сказано, что “в настоящее время мы не поддерживаем миграцию баз данных из одних кластеров DigitalOcean в другие кластеры в рамках DigitalOcean”.

Короче говоря, нам нужно было переносить базу данных своими силами, и мы предоставили клиенту два варианта решения этой задачи:

  1. pg_dump

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

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

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

Предварительные требования для миграции

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

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

Сделать базу данных общедоступной: Для миграции базы данных имя хоста или IP-адрес исходной базы данных должны быть доступны из публичного интернета. Информация о публичном подключении к базам данных DigitalOcean находится в разделе “Connection Details” на панели управления базой данных.

Разрешить удаленные подключения: Во-первых, убедитесь, что база данных разрешает все удаленные подключения. Это определяется переменной базы данных listen_addresses, которая разрешает все удаленные подключения, если ее значение равно. Чтобы проверить ее текущее значение, выполните в терминале PostgreSQL (psql) следующий запрос:

SHOW listen_addresses;
If enabled, the command line returns:
listen_addresses
-----------
*
(1 row)

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

ALTER SYSTEM SET listen_addresses = '*';

Мы также должны изменить ваше локальное IPv4-соединение, чтобы разрешить все входящие IP-адреса. Для этого вам нужно найти файл конфигурации pg_hba.conf с помощью следующего запросом:

SHOW hba_file;

Откройте pg_hba.conf в текстовом редакторе по вашему выбору, например, nano: nano pg_hba.conf

В разделе “IPv4 local connections” найдите и замените IP-адрес на 0.0.0.0/0, что разрешат все IPv4-адреса:

# TYPE DATABASE USER ADDRESS METHOD
 
# IPv4 local connections:
host all all 0.0.0.0/0 md5
# IPv6 local connections:
host all all ::/0 md5

Включение логической репликации

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

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

show wal_level;
If enabled, the output returns:
wal_level
-----------
logical
(1 row)
If the output is different, enable logical replication in your database by setting wal_level to logical:
ALTER SYSTEM SET wal_level = logical;

Изменение максимального количества слотов репликации

После включения логической репликации нам нужно убедиться, что значение max_replication_slots вашей базы данных равно или превышает количество баз данных на вашем PostgreSQL сервере. Чтобы проверить текущее значение, выполните следующий запрос в терминале PostgreSQL (psql):

show max_replication_slots;

Вывод будет выглядеть следующим образом:

max_replication_slots
-----------

(1 row)

Если это значение меньше, чем количество баз данных на нашем PostgreSQL сервере, измените его, выполнив следующий запрос, где use_your_number — это количество баз данных на нашем сервере:

ALTER SYSTEM SET max_replication_slots = use_your_number;

И перезагрузите сервер.

Проблемы, с которыми мы можем столкнуться во время миграции

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

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

Предостережения

  • Он не поддерживает DELETE/UPDATE без репликационного идентификатора.

  • Уникальный индекс нельзя использовать с репликационным идентификатором, если разрешены NULL-значения.

  • Используется REPLICA IDENTITY FULL.

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

  • Из-за дополнительного логирования создается огромное количество WAL.

  • Этот метод может быть медленнее, чем традиционный.

Что следует учитывать

И так, нам нужно установить репликационный идентификатор FULL для таблиц, которые переносятся логически только по UNIQUE ключу, иначе DELETE/UPDATE не будет поддерживаться.

После того, как данные из форка DBaaS будут синхронизированы на новую виртуальную машину на дроплете, нам нужно выполнить методы pg_dump и pg_restore для последовательностей. У вас может возникнуть вопрос: зачем нам дамп последовательности и почему мы не можем реплицировать ее с помощью логической репликации?

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

  • Сделайте дамп последовательностей из форка БД DBaaS

  • Остановите форк БД DBaaS

  • Восстановите последовательности на новом дроплете

  • Отключите логические подписки

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

Исходный кластер: DBasS Digital Ocean 

Место назначения: дроплеты Digital Ocean

Процесс:

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

  • На целевой виртуальной машине мы установили дистрибутив Percona для PostgreSQL 13.7.

  • Перенесли в место назначения роли из исходного кластера, т.е. DBasS.

  • Сформировали список таблиц, у которых нет первичного ключа, и проинформировал их.

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

  • Установили на виртуальную машину расширения, которые были в исходном кластере.

  • Сформировали дамп схемы из исходного кластера, т.е. DBasS.

  • Восстановили ​​схему на месте назначения, т.е. на дроплетых.

  • Скорректировали в исходном кластере и месте назначения параметры, связанные с логической репликацией, такие как max_replication_slots, max_logical_replication_workers и max_wal_senders.

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

  • Как только место назначения было синхронизировано, отключили подписчиков.

  • Сформировали дамп последовательностей из исходного кластера и восстановили их в месте назначения.

  • Скорректировали файлы listen_address, pg_hba на месте назначения.

  • Сбросили подписчиков на месте назначения.

Заключение

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


В заключение статьи приглашаем всех желающих на открытое занятие «Автоматизация развертывания на кластера PostgreSQL на базе Patroni в Kubernetes», которое пройдет в рамках онлайн-курса "PostgreSQL Cloud Solutions".

На этом открытом уроке будет разыграна книга руководителя курса Евгения Аристова — «PostgreSQL 14. Оптимизация, Kubernetes, кластера, облака».

Комментарии (1)


  1. TyVik
    00.00.0000 00:00

    Делать публичной любую бд очень опасно. На пет-проекте забыл включить фаервол обратно, а на следующий день уже восстанавливался из бэкапа.

    У Postgres есть возможность разрешить подключения с конкретных IP адресов. Не нужно открывать всему миру.