Недавно один из наших клиентов обратился к нам с одной интересной задачей: ему нужно было перенести весь свой кластер PostgreSQL с DBaaS (Database as a Service) на дроплет в рамках DigitalOcean. Причиной их перехода с DBaaS на дроплеты была их более низкая стоимость. Эта задача оказалась довольно сложной, поскольку в документации DigitalOcean четко сказано, что “в настоящее время мы не поддерживаем миграцию баз данных из одних кластеров DigitalOcean в другие кластеры в рамках DigitalOcean”.
Короче говоря, нам нужно было переносить базу данных своими силами, и мы предоставили клиенту два варианта решения этой задачи:
pg_dump
Логическая репликация
Метод с 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, кластера, облака».
TyVik
Делать публичной любую бд очень опасно. На пет-проекте забыл включить фаервол обратно, а на следующий день уже восстанавливался из бэкапа.
У Postgres есть возможность разрешить подключения с конкретных IP адресов. Не нужно открывать всему миру.