Порядок перенесення 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.
Загальний план перевірки після будь-якої міграції описано у статті перевірка після міграції, а порядок безпечного відкату — у статті план відкату міграції.