Недавно один из наших клиентов обратился к нам с одной интересной задачей: ему нужно было перенести весь свой кластер 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) следующий запрос: Если ваш результат будет другим, вы можете разрешить удаленные подключения в вашей базе данных, выполнив следующий запрос: Мы также должны изменить ваше локальное IPv4-соединение, чтобы разрешить все входящие IP-адреса. Для этого вам нужно найти файл конфигурации pg_hba.conf с помощью следующего запросом: Откройте pg_hba.conf в текстовом редакторе по вашему выбору, например, nano: nano pg_hba.conf В разделе “IPv4 local connections” найдите и замените IP-адрес на 0.0.0.0/0, что разрешат все IPv4-адреса: У большинства поставщиков облачных баз данных логическая репликация включена по умолчанию. Логическая репликация может быть не включена, если вы переносите базу данных с локального сервера. Если ваша база данных не подготовлена для логической репликации, то процесс миграции не будет работать, поскольку база данных может перемещать только ваши схемы, а не сами данные. Чтобы убедиться, что логическая репликация включена, выполните следующий запрос в терминале PostgreSQL (psql): После включения логической репликации нам нужно убедиться, что значение max_replication_slots вашей базы данных равно или превышает количество баз данных на вашем PostgreSQL сервере. Чтобы проверить текущее значение, выполните следующий запрос в терминале PostgreSQL (psql): Вывод будет выглядеть следующим образом: Если это значение меньше, чем количество баз данных на нашем PostgreSQL сервере, измените его, выполнив следующий запрос, где 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, кластера, облака». Регистрация на открытый урок