Перенос PostgreSQL на другой сервер: дамп, роли и проверка
Покажу перенос одной базы через pg_dump и pg_restore. С подготовкой новой площадки, проверкой данных и понятным моментом, когда приложение можно переключать.
Когда подходит перенос через дамп
Разберём перенос одной базы PostgreSQL 16 на другой сервер той же основной версии. Есть доступ к исходной базе, место под копию и согласованное время остановки записи. Это не перенос всего приложения: файлы, очереди, настройки и внешние подключения проверяются отдельно.
Если база большая, запись нельзя надолго остановить или нужно сменить основную версию PostgreSQL, сначала нужен другой план. Репликация и обновление версии требуют своих проверок. Если исходная база уже недоступна, переходите к восстановлению из сохранившейся копии. Дамп с недоступного сервера получить не получится.
Что проверить до остановки приложения
- Версии сервера, pg_dump и pg_restore. Старый pg_dump не умеет выгружать более новый сервер. Для этого примера используйте клиентские утилиты PostgreSQL 16.
- Размер базы, свободное место и время пробного восстановления. Небольшой архив может потребовать значительно больше места после распаковки и создания индексов.
- Расширения, кодировки, локали, владельцев объектов и права. На новой площадке должны быть доступны нужные расширения и совместимые настройки.
- Все источники записи: приложение, фоновые задачи, импорты, интеграции и прямые подключения. Остановка сайта не всегда останавливает запись в базу.
pg_dump --version
pg_restore --version
psql -X --host=db-old.internal --username=app --dbname=app \
--command="SHOW server_version;"
psql -X --host=db-old.internal --username=app --dbname=app \
--command="SELECT extname, extversion FROM pg_extension ORDER BY extname;"
Имена серверов, пользователей и баз здесь условные. Подставьте свои. Подключайтесь по защищённой сети, через настроенный SSH-туннель или с TLS по требованиям площадки. Пароль вводите по запросу клиента либо храните в заранее настроенном защищённом файле паролей. Не вставляйте его в команду или репозиторий.
Сначала сделайте репетицию
Проведите пробную выгрузку и восстановление в отдельную базу. Замерьте время, проверьте права и запуск приложения. Для репетиции используйте другое имя, например app_trial, и отключите отправку писем, оплату и фоновые действия во внешних системах.
Команды ниже относятся к финальному переносу. Перед ним остановите все согласованные источники записи. Дождитесь завершения операций, которые должны попасть в новую базу. Пока идёт финальная выгрузка и проверка, запись в старую систему должна оставаться остановленной.
Сделайте финальный дамп
umask 077
pg_dump --host=db-old.internal --username=app --dbname=app \
--format=custom --file=app-final.dump
pg_restore --list app-final.dump > app-final.contents.txt
Проверьте код завершения pg_dump и сообщения об ошибках. Наличие файла само по себе ничего не доказывает. Список содержимого показывает, что архив читается, но не заменяет восстановление.
pg_dump получает согласованный снимок базы. Изменения, записанные после начала этого снимка, в него не попадут. Поэтому команда сама по себе не решает задачу переезда без потери новых заказов.
Один дамп базы не создаёт все роли и табличные пространства кластера. Их перенос планируют отдельно. В примере ниже объекты будут принадлежать одной роли app, а прежние владельцы и права из дампа не применяются. Для системы с несколькими ролями это решение нельзя переносить автоматически.
Подготовьте новую базу и восстановите данные
На новой площадке администратор создаёт роль app, если её ещё нет, и отдельную пустую базу. Пароль новой роли задаётся интерактивно. При наличии готовой роли проверьте её права, не создавайте повторно.
createuser --host=db-new.internal --username=db_admin --pwprompt app
createdb --host=db-new.internal --username=db_admin \
--owner=app --template=template0 app_migrated
pg_restore --host=db-new.internal --username=app --dbname=app_migrated \
--no-owner --no-acl --exit-on-error --single-transaction app-final.dump
У app должны быть права на создание объектов в новой базе. Расширения, требующие повышенных прав, заранее готовит администратор. Не выдавайте приложению superuser только ради обхода ошибки.
Здесь --no-owner и --no-acl сознательно отключают восстановление старых владельцев и разрешений. Это удобно для одной роли в учебном примере, но права остальных пользователей нужно воссоздать и проверить отдельно. --single-transaction делает восстановление одним целым: при ошибке изменения этой попытки откатываются.
Проверьте данные и подключение приложения
psql -X --host=db-new.internal --username=app --dbname=app_migrated \
--command="SELECT current_database(), current_user, inet_server_addr();"
psql -X --host=db-new.internal --username=app --dbname=app_migrated \
--command="ANALYZE;"
Сверьте важные таблицы, последние записи и суммы, значимые для проекта. В учебной базе с таблицей orders можно сравнить такой результат на старой и новой стороне:
SELECT count(*) AS rows, max(id) AS last_id, sum(total) AS total
FROM public.orders;
Это пример проверки, а не универсальное доказательство равенства баз. Одинаковое количество строк не означает одинаковое содержимое. Для вашего проекта могут понадобиться дополнительные сверки.
Подключите приложение к новой базе без открытия записи пользователям. Проверьте вход, чтение данных и создание тестовой записи в согласованном режиме. Проверьте последовательности, права, фоновые задачи и ошибки. Убедитесь, что приложение действительно обращается к новой базе.
Переключите запись и сохраните возможность разобраться
Меняйте настройки подключения только по согласованному плану. После запуска проверьте, куда поступают новые записи. Старые процессы не должны продолжать писать в прежнюю базу.
Возврат после появления новых данных — уже отдельная задача. Простое переключение адреса назад потеряет изменения новой площадки. До запуска договоритесь, как остановить запись, сравнить расхождения и перенести нужные данные при неудаче. Старую систему и финальный дамп не удаляйте до проверки и согласования хранения.
Перенос приложения целиком разобран в общем плане миграции. Если вы учитесь, повторите перенос на маленьком проекте и запишите, какие проверки нашли ошибки. Такой опыт пригодится и в работе, и на собеседовании.
Источники и границы примера
Поведение форматов и параметров сверено с документацией pg_dump, pg_restore и руководством по SQL Dump. Пример рассчитан на одну базу и одного владельца объектов. Это не инструкция по переносу сложного кластера без остановки.
Частые вопросы
Можно ли сделать дамп работающей базы?
Да, pg_dump создаёт согласованный снимок. Но новые изменения после начала снимка не попадут в этот дамп. Для финального переключения нужно согласовать остановку записи или другой способ синхронизации.
Перенесутся ли пользователи и все права автоматически?
Нет. Дамп одной базы не создаёт все роли кластера. В этом примере старые владельцы и права отключены, объекты создаются под ролью app. Систему с несколькими ролями нужно разбирать отдельно.
Можно ли сразу отключить старый сервер?
Сначала проверьте данные, приложение и новые записи. Старую площадку отключают после согласованной проверки и решения о хранении копий.
Если нужна помощь с проектом
Перенос рабочей базы можно поручить мне и команде. Если задача шире одной базы, разберём и остальные части проекта. Обсудить перенос данных.