К основному содержимому

Миграция PostgreSQL между серверами

Миграция · 07.02.2025 · 4 мин чтения
Иллюстрация к статье «Миграция PostgreSQL между серверами»

Порядок переноса PostgreSQL без падения приложения

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

  1. Проверьте версию PostgreSQL на новом сервере — она должна быть равна или новее версии на старом.
  2. Снимите дамп на старом сервере, не останавливая приложение.
  3. Восстановите дамп на новом сервере в пустую базу и сверьте количество строк в ключевых таблицах.
  4. Подключите тестовый экземпляр приложения к новой базе через переменные окружения, не трогая продакшен.
  5. Переключите продакшен на новую базу только после успешной проверки, приняв короткое окно простоя на финальную синхронизацию.

pg_dump: экспорт базы данных

# Дамп одной базы в custom формат (сжатый, параллельный restore)
pg_dump -U postgres -Fc -d mydb > mydb.dump

# Дамп в SQL-формате (читаемый)
pg_dump -U postgres -d mydb > mydb.sql

# Только схема (без данных)
pg_dump -U postgres --schema-only -d mydb > schema.sql

Логическая репликация для минимального простоя

Если простой в несколько минут недопустим, используйте логическую репликацию вместо разового дампа: она непрерывно передаёт изменения на новый сервер, а pg_dump нужен только для первоначальной загрузки.

-- На старом сервере: публикация изменений
CREATE PUBLICATION mydb_pub FOR ALL TABLES;

-- На новом сервере: подписка на публикацию
CREATE SUBSCRIPTION mydb_sub
  CONNECTION 'host=OLD_SERVER dbname=mydb user=repl_user password=secret'
  PUBLICATION mydb_pub;

pg_restore: импорт на новом сервере

# Создаём базу на новом сервере
createdb -U postgres mydb

# Восстановление из custom формата
pg_restore -U postgres -d mydb -j 4 mydb.dump
# -j 4 — использовать 4 процесса параллельно
💡 Custom формат (Fc) в 3–10 раз быстрее восстанавливается чем SQL, и поддерживает параллельный restore с -j.

Быстрая передача через pipe

# Без сохранения дампа на диске
pg_dump -U postgres -Fc mydb | ssh root@NEW_SERVER "pg_restore -U postgres -d mydb"

Сравнение форматов дампа

ФорматФлагПараллельный restoreКогда использовать
Custom-Fcда (-j)стандартный выбор для переноса между серверами
Plain SQLбез флаганетнужно вручную редактировать дамп перед восстановлением
Directory-Fdда (-j)очень большие базы, нужен параллельный сам дамп

Проверка на новом сервере до переключения

Подключите тестовый экземпляр приложения к новому серверу напрямую по IP, не меняя DNS и не трогая продакшен:

DATABASE_URL=postgresql://user:pass@NEW_SERVER_IP:5432/mydb ./run-app --dry-run

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

Проверка после миграции

-- Сравниваем количество строк
SELECT schemaname, tablename, n_live_tup
FROM pg_stat_user_tables
ORDER BY n_live_tup DESC;

Дополнительно проверьте, что все последовательности (SEQUENCE) продолжаются с правильного значения — иначе новые записи начнут конфликтовать по первичному ключу:

SELECT setval('orders_id_seq', (SELECT MAX(id) FROM orders));

Типичные ошибки при восстановлении

СообщениеПричина и решение
FATAL: password authentication failed for userНе совпадает метод аутентификации в pg_hba.conf на новом сервере — добавьте строку с md5 или scram-sha-256 для нужного хоста
pg_restore: error: could not execute query: ERROR: relation already existsВосстановление в непустую базу — создайте новую пустую базу или добавьте флаг --clean
ERROR: invalid byte sequence for encoding "UTF8"Исходная база в другой кодировке — создайте новую базу с явным ENCODING, совпадающим со старой
pg_dump: error: server version mismatchВерсия pg_dump старше версии сервера — используйте бинарник pg_dump той же мажорной версии, что и сервер

Откат при проблемах

  1. Не выключайте старый сервер, пока новый не отработал под реальной нагрузкой хотя бы сутки.
  2. Если после переключения приложение работает нестабильно, верните DATABASE_URL на старый сервер — данные там не тронуты.
  3. Разберитесь с причиной на новом сервере в спокойном режиме и повторите перенос.

Когда это не подходит

Убедитесь что версия PostgreSQL на новом сервере >= версии на старом. Откат на более старую версию не поддерживается. Для баз крупнее 100 ГБ или с требованием нулевого простоя разовый pg_dump/pg_restore слишком долгий — используйте логическую репликацию из раздела выше или физическую репликацию через pg_basebackup.

Общий план проверки после любой миграции описан в статье проверка после миграции, а порядок безопасного отката — в статье план отката миграции.

Статья помогла?
← Назад в базу знаний Задать вопрос поддержке