Новинка Виртуальный VDS сервер в Нидерландах от 390р
Выберите продукт

PostgreSQL pg_dump и pg_restore на VDS: custom format и parallel restore

Разбираем, как безопасно сделать логический бэкап PostgreSQL на VDS через pg_dump в custom format и восстановить его pg_restore с --jobs. Команды, проверки, права, сценарии миграции и нюансы производительности.
PostgreSQL pg_dump и pg_restore на VDS: custom format и parallel restore

Логический бэкап PostgreSQL через pg_dump — один из самых удобных способов перенести базу между серверами, подготовить копию для staging-окружения, проверить обновление приложения или быстро откатиться после неудачной миграции схемы. На VDS это особенно удобно: у вас есть root-доступ, можно контролировать I/O, ставить нужную версию клиентских утилит и запускать восстановление в несколько потоков.

В этой статье разберём практический сценарий: как сделать дамп в custom format, почему это не то же самое, что обычный SQL-файл, как проверить архив до аварии, как восстановить его через pg_restore с --jobs и где обычно ломаются права, расширения, владельцы объектов и производительность.

Короткая идея: pg_dump -F c создаёт гибкий архив, а pg_restore -j умеет восстанавливать его параллельно. Это хороший формат для миграций и регулярных логических бэкапов небольших и средних PostgreSQL-баз на VDS.

Когда выбирать custom format, а когда нет

У pg_dump есть несколько форматов. Самый привычный — plain SQL, когда результат можно открыть в редакторе и выполнить через psql. Он прост, но плохо подходит для выборочного и параллельного восстановления: вы получаете линейный скрипт, который выполняется сверху вниз.

custom format, включаемый опцией -F c или --format=custom, хранит данные в архивном формате PostgreSQL. Такой файл обычно имеет расширение .dump или .backup. Его нельзя просто выполнить через psql; для восстановления используется pg_restore. Зато можно посмотреть содержимое архива, восстановить отдельные схемы или таблицы, исключить владельцев и ACL, а главное — запустить parallel restore.

Есть важная тонкость: custom format поддерживает параллельное восстановление, но не поддерживает параллельное создание дампа. Если нужна именно параллельная выгрузка, используйте directory format: pg_dump -F d -j 4. Для большинства типовых миграций на VDS custom format остаётся удобным компромиссом: один файл проще хранить, копировать, проверять и передавать между серверами.

Не стоит путать логический дамп с физическим бэкапом. pg_dump сохраняет структуру и данные на уровне SQL-объектов, но не является заменой PITR, base backup и архивации WAL. Если нужно восстановление на конкретную секунду после аварии, посмотрите отдельный разбор про PITR и WAL-бэкапы PostgreSQL. Логический дамп, в свою очередь, отлично подходит для переносов, тестовых окружений, смены версии PostgreSQL в разумных пределах и восстановления отдельных объектов.

Подготовка на VDS: версия клиента, место на диске и нагрузка

Первое правило PostgreSQL-бэкапов: версия pg_dump должна быть не старше версии сервера PostgreSQL, с которого вы снимаете дамп. Например, клиент PostgreSQL 16 обычно может снять дамп с сервера 15, но клиент 14 не стоит использовать против сервера 16. При миграции на новый VDS удобно ставить клиентские утилиты той же мажорной версии, что и исходная база, либо новее.

Проверьте версии:

psql --version
pg_dump --version
pg_restore --version

Для установки клиентских утилит используйте пакет PostgreSQL из репозитория вашей ОС или официальный репозиторий PostgreSQL, если нужна конкретная мажорная версия. Ниже — базовые команды из стандартных репозиториев.

Debian и Ubuntu

sudo apt update
sudo apt install postgresql-client

AlmaLinux, Rocky Linux, CentOS Stream, Oracle Linux и Fedora

sudo dnf install postgresql

Перед дампом оцените размер базы и свободное место. Архив custom format с компрессией часто меньше самой базы, но это не гарантия: многое зависит от типов данных, индексов, TOAST-данных и уже сжатого содержимого. Для восстановления нужно место не только под дамп, но и под новую базу, временные файлы, индексы и WAL.

psql -U postgres -d appdb -c 'select pg_size_pretty(pg_database_size(current_database()));'
df -h
free -h

На небольшом VDS не запускайте тяжёлый дамп в час пик без ограничения приоритета. pg_dump читает много данных и может конкурировать с рабочим приложением за диск и CPU. Для мягкого запуска пригодятся nice и ionice:

nice -n 10 ionice -c2 -n7 pg_dump -h 127.0.0.1 -U app_backup -d appdb -F c -Z 6 -f /backup/appdb_$(date +%F_%H%M).dump

Параметр -Z задаёт уровень сжатия. Чем выше уровень, тем меньше файл, но тем больше CPU. На VDS с ограниченным числом vCPU обычно разумно начинать с -Z 4 или -Z 6, а не сразу с максимума.

Проверка места на диске и версии утилит перед бэкапом PostgreSQL

Пользователь для бэкапа: меньше прав, меньше сюрпризов

Технически дамп можно снять от имени суперпользователя PostgreSQL, но для регулярных задач лучше завести отдельную роль. Она должна уметь подключаться к базе и читать нужные схемы, таблицы и последовательности. Если в базе много схем, выдавайте права осознанно, а не только на public.

CREATE ROLE app_backup WITH LOGIN PASSWORD 'replace_with_long_password';
GRANT CONNECT ON DATABASE appdb TO app_backup;
GRANT USAGE ON SCHEMA public TO app_backup;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO app_backup;
GRANT SELECT ON ALL SEQUENCES IN SCHEMA public TO app_backup;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO app_backup;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON SEQUENCES TO app_backup;

Если дамп должен включать расширения, функции, типы, схемы и все объекты без ошибок доступа, иногда проще выполнять его владельцем базы или ролью с более широкими правами. Но для автоматического ночного бэкапа лучше начать с минимальной роли и один раз проверить журнал дампа. Ошибка прав не всегда означает полный провал, но в бэкапе могут отсутствовать важные объекты.

Пароль не стоит передавать прямо в командной строке: он попадёт в историю shell или список процессов. Используйте файл .pgpass. На Debian/Ubuntu домашний каталог системного пользователя PostgreSQL обычно /var/lib/postgresql, на RHEL-based системах — /var/lib/pgsql. Для отдельного пользователя, от которого запускается бэкап, путь будет его домашним каталогом.

install -m 600 /dev/null ~/.pgpass
printf '127.0.0.1:5432:appdb:app_backup:replace_with_long_password' > ~/.pgpass
chmod 600 ~/.pgpass

Создаём дамп PostgreSQL в custom format

Базовая команда выглядит так:

pg_dump -h 127.0.0.1 -p 5432 -U app_backup -d appdb -F c -Z 6 -f /backup/appdb_$(date +%F_%H%M).dump

Разберём важные параметры. -h и -p задают адрес и порт сервера. -U — роль подключения. -d — база. -F c включает custom format. -Z задаёт компрессию. -f указывает файл архива.

Если база большая, добавьте подробный вывод:

pg_dump -h 127.0.0.1 -U app_backup -d appdb -F c -Z 6 --verbose -f /backup/appdb_$(date +%F_%H%M).dump

Для миграции между серверами часто полезно не включать владельцев и права доступа в восстановление, но сами эти параметры задаются на этапе pg_restore, а не обязательно на этапе pg_dump. Это удобно: один и тот же архив можно восстановить в production-like окружение с владельцами или в staging без них.

Если нужно выгрузить только одну схему:

pg_dump -h 127.0.0.1 -U app_backup -d appdb -n public -F c -Z 6 -f /backup/appdb_public.dump

Если нужно исключить тяжёлую таблицу с временными или аналитическими данными:

pg_dump -h 127.0.0.1 -U app_backup -d appdb -F c -Z 6 --exclude-table-data=public.event_log -f /backup/appdb_without_event_log.dump

Опция --exclude-table-data исключает только данные, но оставляет структуру таблицы. Это полезно для staging: приложение видит таблицу, миграции проходят, но восстановление не тратит часы на исторический лог.

FastFox VDS
Облачный VDS-сервер
Виртуальные серверы с быстрым запуском и гибкой конфигурацией от 390₽ / мес
Доступные локации
Россия Нидерланды

Проверяем архив до того, как он понадобится

Бэкап без проверки — это предположение, а не защита. Минимальная проверка custom-архива — прочитать его оглавление через pg_restore --list. Если архив повреждён или создан несовместимой версией, вы узнаете об этом сразу.

pg_restore --list /backup/appdb_2026-01-15_0300.dump

Список можно сохранить в файл. Потом его удобно использовать для выборочного восстановления или исключения объектов:

pg_restore --list --file=/backup/appdb_restore.list /backup/appdb_2026-01-15_0300.dump

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

createdb -h 127.0.0.1 -U postgres appdb_restore_test
pg_restore -h 127.0.0.1 -U postgres -d appdb_restore_test --verbose /backup/appdb_2026-01-15_0300.dump
psql -h 127.0.0.1 -U postgres -d appdb_restore_test -c 'select count(*) from public.users;'
dropdb -h 127.0.0.1 -U postgres appdb_restore_test

Для автоматической проверки можно восстанавливать дамп на отдельном VDS или в отдельном PostgreSQL-кластере. Важно не запускать тестовое восстановление в рабочую базу и не использовать имя production-базы в скриптах проверки.

Восстановление через pg_restore: безопасный базовый сценарий

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

createdb -h 127.0.0.1 -U postgres -O app_owner appdb_new
pg_restore -h 127.0.0.1 -U postgres -d appdb_new --verbose /backup/appdb.dump

Если на новом сервере нет тех же ролей, что были на старом, восстановление может ругаться на владельцев и привилегии. Для миграции между VDS часто используют --no-owner и --no-acl, а владельца задают через --role или через владельца базы.

createdb -h 127.0.0.1 -U postgres -O app_owner appdb_new
pg_restore -h 127.0.0.1 -U postgres -d appdb_new --no-owner --no-acl --role=app_owner --verbose /backup/appdb.dump

Если нужно восстановить поверх существующей базы, используйте --clean и --if-exists. Будьте осторожны: команда удаляет объекты, которые есть в архиве, перед повторным созданием.

pg_restore -h 127.0.0.1 -U postgres -d appdb --clean --if-exists --no-owner --no-acl --verbose /backup/appdb.dump

Для production-восстановления сначала прогоните команду на тестовой базе с тем же архивом. Большинство неприятных ошибок — роли, расширения, collation, права на схемы — лучше увидеть до окна работ.

Parallel restore: как ускорить восстановление custom format

Главная причина выбирать custom format для крупных логических бэкапов — pg_restore --jobs. Параллельное восстановление позволяет одновременно загружать данные, создавать индексы и выполнять независимые части архива. На VDS это может дать заметный выигрыш, особенно если база содержит много таблиц и индексов.

createdb -h 127.0.0.1 -U postgres -O app_owner appdb_new
pg_restore -h 127.0.0.1 -U postgres -d appdb_new --jobs=4 --no-owner --no-acl --role=app_owner --verbose /backup/appdb.dump

Число потоков не должно быть «чем больше, тем лучше». Начните с количества vCPU или чуть меньше. Для VDS с 2 vCPU обычно разумно --jobs=2. Для 4 vCPU — --jobs=3 или --jobs=4. Если диск начинает упираться в I/O wait, увеличение потоков только ухудшит ситуацию.

Параллельное восстановление потребляет больше соединений к PostgreSQL. Проверьте max_connections и не запускайте восстановление рядом с нагруженным приложением в той же базе. Также учитывайте память: при одновременном создании индексов может умножаться потребление maintenance_work_mem. Если задать слишком большое значение и включить много jobs, сервер уйдёт в swap или получит OOM.

На время восстановления в новую базу можно аккуратно увеличить параметры, которые влияют на создание индексов и запись WAL. Делайте это осознанно и возвращайте значения после работ:

psql -U postgres -d postgres -c 'alter system set maintenance_work_mem = ''512MB'';'
psql -U postgres -d postgres -c 'alter system set checkpoint_timeout = ''15min'';'
psql -U postgres -d postgres -c 'alter system set max_wal_size = ''4GB'';'
psql -U postgres -d postgres -c 'select pg_reload_conf();'

Если VDS небольшой, лучше не ставить агрессивные значения. Например, при 2 ГБ RAM maintenance_work_mem в 512 МБ и --jobs=4 уже может быть рискованной комбинацией. Смотрите на реальное потребление через htop, vmstat, iostat и логи PostgreSQL.

Нельзя одновременно рассчитывать на все гарантии сразу. Например, --single-transaction полезен для атомарного восстановления, но плохо сочетается с параллельным режимом: для ускорения обычно выбирают --jobs, а для максимально строгого единичного применения — транзакционный сценарий без параллелизма.

Параллельное восстановление PostgreSQL через pg_restore jobs

Восстановление отдельных таблиц, схем и объектов

Custom format удобен тем, что не заставляет восстанавливать всё сразу. Можно достать одну таблицу, схему или данные без полного разворота базы. Например, восстановим только таблицу public.orders в уже подготовленную базу:

pg_restore -h 127.0.0.1 -U postgres -d appdb_recovery --table=public.orders --data-only --verbose /backup/appdb.dump

Для восстановления схемы:

pg_restore -h 127.0.0.1 -U postgres -d appdb_recovery --schema=public --verbose /backup/appdb.dump

Более гибкий способ — отредактировать список объектов. Сначала создайте list-файл, затем закомментируйте ненужные строки и восстановите только оставшееся:

pg_restore --list --file=/backup/appdb_restore.list /backup/appdb.dump
pg_restore -h 127.0.0.1 -U postgres -d appdb_recovery --use-list=/backup/appdb_restore.list --verbose /backup/appdb.dump

Этот подход особенно полезен, когда нужно вернуть одну случайно удалённую таблицу, но у неё есть зависимости: последовательности, индексы, constraints. В list-файле видно порядок объектов, и можно точнее управлять восстановлением.

Миграция базы между двумя VDS

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

sha256sum /backup/appdb.dump
scp /backup/appdb.dump admin@new-vds:/backup/appdb.dump

На новом сервере снова проверьте сумму:

sha256sum /backup/appdb.dump

Если окно простоя должно быть коротким, логический дамп большого production может оказаться недостаточным: пока вы снимаете дамп, данные продолжают меняться. Для небольших проектов обычно делают так: заранее переносят файлы приложения, настраивают PostgreSQL, DNS, веб-сервер и SSL, затем в окно работ переводят приложение в read-only или maintenance-режим, снимают финальный дамп, восстанавливают его и переключают трафик. Для крупных систем лучше рассмотреть логическую репликацию или физическую репликацию с последующим switchover.

После восстановления обязательно проверьте расширения и настройки локали. Некоторые расширения должны быть установлены на уровне ОС до восстановления, иначе pg_restore не сможет создать их в базе.

psql -U postgres -d appdb_new -c 'select extname, extversion from pg_extension order by extname;'
psql -U postgres -d appdb_new -c 'select datname, datcollate, datctype from pg_database where datname = current_database();'

Автоматизация через systemd timer

На VDS лучше не полагаться только на ручные команды. Для регулярного логического бэкапа можно использовать простой shell-скрипт и systemd timer. Ниже пример без сложной ротации: он создаёт custom-дамп, пишет лог и удаляет архивы старше 14 дней. Если хотите выносить копии на отдельное хранилище, пригодится материал про бэкапы в S3-совместимое хранилище через restic и Borg.

sudo install -d -m 750 -o postgres -g postgres /backup/postgresql
sudo install -m 750 -o postgres -g postgres /dev/null /usr/local/sbin/pgdump-appdb.sh
#!/bin/sh
set -eu
BACKUP_DIR=/backup/postgresql
DB_NAME=appdb
DB_USER=app_backup
STAMP=$(date +%F_%H%M)
FILE=${BACKUP_DIR}/${DB_NAME}_${STAMP}.dump
pg_dump -h 127.0.0.1 -U ${DB_USER} -d ${DB_NAME} -F c -Z 6 --verbose -f ${FILE}
pg_restore --list ${FILE} >/dev/null
sha256sum ${FILE} > ${FILE}.sha256
find ${BACKUP_DIR} -type f -name '*.dump' -mtime +14 -delete
find ${BACKUP_DIR} -type f -name '*.sha256' -mtime +14 -delete

После создания скрипта назначьте владельца и права:

sudo chown postgres:postgres /usr/local/sbin/pgdump-appdb.sh
sudo chmod 750 /usr/local/sbin/pgdump-appdb.sh

Unit-файл /etc/systemd/system/pgdump-appdb.service:

[Unit]
Description=PostgreSQL logical backup for appdb

[Service]
Type=oneshot
User=postgres
Group=postgres
ExecStart=/usr/local/sbin/pgdump-appdb.sh

Timer-файл /etc/systemd/system/pgdump-appdb.timer:

[Unit]
Description=Run PostgreSQL logical backup for appdb daily

[Timer]  03:20:00
Persistent=true
RandomizedDelaySec=10min

[Install]
WantedBy=timers.target

Включите таймер и проверьте журнал:

sudo systemctl daemon-reload
sudo systemctl enable --now pgdump-appdb.timer
systemctl list-timers pgdump-appdb.timer
journalctl -u pgdump-appdb.service -n 100 --no-pager

Если бэкапы хранятся только на том же диске, что и PostgreSQL, это защита от логической ошибки, но не от потери VDS или диска. Минимально разумная схема — держать свежую локальную копию для быстрого восстановления и внешнюю копию на отдельном сервере или объектном хранилище. Периодически проверяйте не только наличие файлов, но и возможность восстановления.

Типовые ошибки pg_dump и pg_restore

Ошибка: input file does not appear to be a valid archive

Обычно это означает, что вы пытаетесь открыть plain SQL-файл через pg_restore или файл повреждён. Если дамп создавался без -F c, восстанавливайте его через psql. Если файл должен быть custom-архивом, проверьте размер, контрольную сумму и повторите копирование.

Ошибки владельцев и ролей

Сообщения о несуществующих ролях часто появляются при переносе между серверами. Если точное сохранение владельцев не требуется, используйте --no-owner и --no-acl. Если требуется, заранее создайте роли на новом сервере и только потом запускайте восстановление.

Ошибки расширений

Если в базе использовались postgis, pg_trgm, uuid-ossp или другие расширения, убедитесь, что соответствующие пакеты установлены на новом VDS. Простое наличие записи в дампе не гарантирует, что PostgreSQL сможет создать extension без файлов расширения на сервере.

Медленное восстановление индексов

Создание индексов часто занимает больше времени, чем загрузка данных. Помогают быстрый диск, умеренный --jobs, достаточный maintenance_work_mem и отсутствие конкурирующей нагрузки. Но не разгоняйте все параметры сразу: на маленьком VDS избыток параллелизма легко превращается в swap и деградацию.

Дамп зависает или идёт слишком долго

pg_dump работает в согласованном снимке данных, но всё равно читает таблицы и может долго идти по большим объектам. Проверьте активность через pg_stat_activity, нагрузку на диск и наличие долгих транзакций. Если база очень большая, возможно, для регулярных бэкапов лучше использовать физический backup-подход, а логический дамп оставить для миграций и выборочного восстановления.

Практический чек-лист перед боевым восстановлением

  • Проверьте, что версия pg_restore совместима с архивом и целевым PostgreSQL.
  • Убедитесь, что на VDS хватает места под дамп, базу, индексы, временные файлы и WAL.
  • Создайте нужные роли, базу, владельца и установите расширения.
  • Сначала восстановите архив в отдельную тестовую базу.
  • Для миграции между серверами используйте --no-owner и --no-acl, если роли отличаются.
  • Подберите --jobs по vCPU, памяти и I/O, а не по максимальному числу.
  • После восстановления выполните ANALYZE, если статистика неактуальна или приложение строит плохие планы запросов.
  • Проверьте приложение, миграции, фоновые воркеры и права подключения до переключения трафика.

После большого восстановления полезно обновить статистику:

vacuumdb -h 127.0.0.1 -U postgres -d appdb_new --analyze-in-stages

--analyze-in-stages помогает быстрее получить первичную статистику для планировщика, а затем уточнить её. Это особенно заметно после переноса базы, когда приложение сразу начинает выполнять сложные запросы.

Итоги

pg_dump в custom format — практичный инструмент для PostgreSQL на VDS: один архив, гибкое восстановление, выбор объектов и поддержка parallel restore через pg_restore --jobs. Он не заменяет физические бэкапы и PITR, но отлично закрывает задачи миграции, тестового восстановления, staging-копий и регулярных логических снимков.

Главное — не ограничиваться командой создания дампа. Проверяйте архив через pg_restore --list, периодически восстанавливайте его в тестовую базу, следите за версиями утилит, правами, расширениями и местом на диске. Тогда в реальный момент восстановления у вас будет не надежда на бэкап, а проверенная процедура.

Поделиться статьей

Вам будет интересно

Netplan на Ubuntu VDS: статический IPv4/IPv6, default route, DNS и безопасное применение по SSH OpenAI Статья написана AI (GPT 5)

Netplan на Ubuntu VDS: статический IPv4/IPv6, default route, DNS и безопасное применение по SSH

Пошаговая инструкция по Netplan для Ubuntu VDS: как найти интерфейс, прописать static IP, IPv6, default route и DNS, проверить net ...
Linux TCP backlog на VDS: somaxconn, tcp_max_syn_backlog, Nginx и PHP-FPM OpenAI Статья написана AI (GPT 5)

Linux TCP backlog на VDS: somaxconn, tcp_max_syn_backlog, Nginx и PHP-FPM

Когда сайт получает всплеск соединений, узкое место может быть не в CPU, а в очередях TCP. Поясняем, как увидеть переполнение back ...
NFSv4 на Linux VDS: exports, idmapd, firewall и systemd automount OpenAI Статья написана AI (GPT 5)

NFSv4 на Linux VDS: exports, idmapd, firewall и systemd automount

Разберём, как поднять NFSv4 Linux на VDS для общих каталогов: подготовить сервер и клиентов, описать exports, настроить idmapd, от ...