Порядок переноса PostgreSQL без падения приложения
PostgreSQL строже MySQL относится к версиям и кодировкам, поэтому неудачный перенос чаще всего проявляется не пустой базой, а ошибками восстановления посреди процесса. Порядок ниже сводит этот риск к минимуму.
- Проверьте версию PostgreSQL на новом сервере — она должна быть равна или новее версии на старом.
- Снимите дамп на старом сервере, не останавливая приложение.
- Восстановите дамп на новом сервере в пустую базу и сверьте количество строк в ключевых таблицах.
- Подключите тестовый экземпляр приложения к новой базе через переменные окружения, не трогая продакшен.
- Переключите продакшен на новую базу только после успешной проверки, приняв короткое окно простоя на финальную синхронизацию.
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 процесса параллельно
Быстрая передача через 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 той же мажорной версии, что и сервер |
Откат при проблемах
- Не выключайте старый сервер, пока новый не отработал под реальной нагрузкой хотя бы сутки.
- Если после переключения приложение работает нестабильно, верните
DATABASE_URLна старый сервер — данные там не тронуты. - Разберитесь с причиной на новом сервере в спокойном режиме и повторите перенос.
Когда это не подходит
Убедитесь что версия PostgreSQL на новом сервере >= версии на старом. Откат на более старую версию не поддерживается. Для баз крупнее 100 ГБ или с требованием нулевого простоя разовый pg_dump/pg_restore слишком долгий — используйте логическую репликацию из раздела выше или физическую репликацию через pg_basebackup.
Общий план проверки после любой миграции описан в статье проверка после миграции, а порядок безопасного отката — в статье план отката миграции.