Перейти к содержимому
VDS · Базы данных

Резервные копии баз данных

Как настроить дампы MySQL и PostgreSQL по расписанию, увезти их с машины и проверить, что копия действительно восстанавливается.

Обновлено 23 августа 2026 г.

Автоматических резервных копий машины и снимков состояния у VDS нет: всё, что вы не скопировали сами, существует в одном экземпляре. Дамп базы — первое, что стоит настроить, потому что данные восстановить неоткуда, а сайт можно развернуть заново.

Дамп вручную

PostgreSQL:

pg_dump -Fc -U shop -h 127.0.0.1 shop > /srv/backups/shop-$(date +%F).dump
pg_dumpall -U postgres --roles-only > /srv/backups/roles.sql

MySQL и MariaDB:

mysqldump --single-transaction --quick --routines --events \
  -u root shop | gzip > /srv/backups/shop-$(date +%F).sql.gz

--single-transaction снимает согласованный дамп InnoDB без блокировки таблиц — без него сайт встанет на время выгрузки. Формат -Fc у PostgreSQL сжат и позволяет восстанавливать отдельные таблицы.

Пароли в командной строке не пишите: заведите ~/.pgpass или ~/.my.cnf с правами 600.

По расписанию

mkdir -p /srv/backups && chmod 700 /srv/backups
crontab -e
20 3 * * * /usr/local/bin/db-backup.sh >> /var/log/db-backup.log 2>&1

Скрипт /usr/local/bin/db-backup.sh:

#!/bin/bash
set -euo pipefail
DEST=/srv/backups
STAMP=$(date +%F-%H%M)
pg_dump -Fc -U shop -h 127.0.0.1 shop > "$DEST/shop-$STAMP.dump.tmp"
mv "$DEST/shop-$STAMP.dump.tmp" "$DEST/shop-$STAMP.dump"
find "$DEST" -name '*.dump' -mtime +14 -delete

Запись во временный файл с последующим переименованием важна: если дамп оборвётся, вы не примете обрубок за готовую копию. set -euo pipefail останавливает скрипт на первой ошибке вместо тихого продолжения.

Увезти с машины

Копия на том же диске не спасает от ошибки в миграции, шифровальщика и от переустановки системы на вкладке «Доступ». Отправляйте дампы наружу:

rsync -az --delete /srv/backups/ backup@другой-хост:/store/vds/

Или в любое S3-совместимое хранилище через rclone. Учитывайте полосу до 500 Мбит/с и лимит записи на диск по ступени: 60 МБ/с на ядро.

Проверка восстановления

Копия, которую ни разу не разворачивали, копией не является.

createdb -U postgres shop_check
pg_restore -U postgres -d shop_check /srv/backups/shop-2026-08-23.dump
psql -U postgres -d shop_check -c "SELECT count(*) FROM users;"
dropdb -U postgres shop_check

Для MySQL: gunzip -c дамп.sql.gz | mysql -u root shop_check.

Делайте это раз в месяц и записывайте дату проверки.

Частые ошибки

СимптомПричина
Дамп весит несколько килобайтСкрипт упал на аутентификации, ошибка ушла в /dev/null
Кончилось место на дискеНет удаления старых копий по mtime
Восстановление падает на правахРоли не выгружены — нужен --roles-only
Cron молчит, копий нетВ cron нет вашего PATH — пишите абсолютные пути
Сайт тормозит ночьюДамп конкурирует за диск — сдвиньте время, добавьте --quick

Храните минимум две копии в разных местах и следите за размером дампа: резкое падение объёма — признак того, что выгрузилась не вся база.