Зачем автобэкап БД
Без автоматического бэкапа БД — рано или поздно случится катастрофа. Сервер упадёт, диск выйдет из строя, разработчик случайно сделает DROP TABLE без WHERE. Бэкап — последняя линия защиты от потери данных. По данным Gartner, 60% компаний без правильной backup-стратегии разоряются в течение 6 месяцев после крупной потери данных.
Cron — простейший способ автоматизации. Скрипт раз в день делает бэкап, проверяет успех, отправляет в облако, чистит старые файлы, пишет в лог. Всё за 50 строк bash. В этом руководстве — готовые скрипты для PostgreSQL и MySQL.
Готовые скрипты
PostgreSQL — pg_dump
#!/bin/bash
# /opt/scripts/backup-postgres.sh
set -e # exit on error
DB_NAME="myapp"
DB_USER="postgres"
BACKUP_DIR="/var/backups/postgres"
DATE=$(date +%Y-%m-%d_%H-%M-%S)
BACKUP_FILE="$BACKUP_DIR/myapp_$DATE.sql.gz"
mkdir -p "$BACKUP_DIR"
# Бэкап с компрессией
PGPASSWORD="$DB_PASSWORD" pg_dump \
-U "$DB_USER" \
-d "$DB_NAME" \
--format=custom \
--compress=9 \
--file="$BACKUP_FILE.dump"
# Проверка размера (если меньше 1MB — что-то не так)
SIZE=$(stat -c%s "$BACKUP_FILE.dump")
if [ "$SIZE" -lt 1048576 ]; then
echo "ERROR: backup too small ($SIZE bytes)"
curl -X POST "$SLACK_WEBHOOK" -d \
"{\"text\":\"⚠️ Backup PostgreSQL failed!\"}"
exit 1
fi
# Отправка в S3
aws s3 cp "$BACKUP_FILE.dump" \
"s3://my-backups/postgres/$DATE.dump" \
--storage-class STANDARD_IA
# Ротация: удалить локальные файлы старше 7 дней
find "$BACKUP_DIR" -name "*.dump" -mtime +7 -delete
# Лог успеха
echo "$(date): Backup OK ($SIZE bytes)" >> /var/log/backup.logCrontab — расписание
# Установка: crontab -e # Алерт при failure — email админу MAILTO="admin@example.com" # PostgreSQL — каждый день в 3:00 0 3 * * * /opt/scripts/backup-postgres.sh # MySQL — каждый день в 4:00 (отдельная нагрузка) 0 4 * * * /opt/scripts/backup-mysql.sh # Проверка целостности — раз в неделю воскресенье в 5:00 0 5 * * 0 /opt/scripts/verify-backup.sh # Месячный архив — 1-го числа в 6:00 0 6 1 * * /opt/scripts/archive-monthly.sh
MySQL — mysqldump
#!/bin/bash # /opt/scripts/backup-mysql.sh set -e DB_NAME="myapp" DB_USER="root" BACKUP_DIR="/var/backups/mysql" DATE=$(date +%Y-%m-%d) BACKUP_FILE="$BACKUP_DIR/myapp_$DATE.sql.gz" mkdir -p "$BACKUP_DIR" # Бэкап с компрессией mysqldump \ -u "$DB_USER" \ -p"$MYSQL_PASSWORD" \ --single-transaction \ --quick \ --triggers \ --routines \ --events \ "$DB_NAME" | gzip > "$BACKUP_FILE" SIZE=$(stat -c%s "$BACKUP_FILE") if [ "$SIZE" -lt 1048576 ]; then echo "ERROR: MySQL backup too small" exit 1 fi # Шифрование (если данные содержат ПДн) gpg --batch --encrypt \ --recipient backup@example.com \ "$BACKUP_FILE" rm "$BACKUP_FILE" # В S3 aws s3 cp "$BACKUP_FILE.gpg" \ "s3://my-backups/mysql/$DATE.sql.gz.gpg" # Ротация find "$BACKUP_DIR" -name "*.gpg" -mtime +7 -delete echo "$(date): MySQL backup OK ($SIZE bytes)" >> /var/log/backup.log
Правило 3-2-1: 3 копии данных (одна основная, две backup), на 2 разных типах носителей, 1 копия offsite (в другом физическом месте). Это минимум для защиты от любых типов потери данных — от поломки диска до пожара в датацентре.— 3-2-1 Backup Rule, US-CERT
Ротация и storage
Стандартная схема ротации
- Daily backup — последние 7 дней.
- Weekly backup (воскресенье) — последние 4 недели.
- Monthly backup (1-е число) — последние 12 месяцев.
- Yearly backup (1 января) — постоянное хранение.
#!/bin/bash # /opt/scripts/rotate-backups.sh # Ежедневные — 7 дней find /var/backups/daily -mtime +7 -delete # Еженедельные — 4 недели = 28 дней find /var/backups/weekly -mtime +28 -delete # Ежемесячные — 12 месяцев = 365 дней find /var/backups/monthly -mtime +365 -delete # Yearly — не удалять, переносим в archive mv /var/backups/yearly/* /mnt/archive/yearly/ echo "Rotation complete: $(date)" >> /var/log/backup.log
Storage tiers
- Hot (быстрый доступ). Локальный диск или Yandex Object Storage Standard. Daily backups последних 7 дней. Используется для regular rollback.
- Warm (медленный, дешёвый). S3 Glacier Instant Retrieval / Yandex Cold. Weekly + monthly. Достаём за минуты при disaster recovery.
- Cold (архив, очень дешёвый). S3 Glacier Deep Archive / Yandex Cold long-term. Yearly + compliance. Достаём за 12-48 часов.
Восстановление
PostgreSQL restore
# Полное восстановление pg_restore -U postgres -d myapp_restored backup.dump # В чистую БД createdb myapp_restored pg_restore -U postgres -d myapp_restored \ --clean --if-exists backup.dump # Восстановление одной таблицы pg_restore -U postgres -d myapp \ --table=users backup.dump # Просмотр содержимого без восстановления pg_restore -l backup.dump
MySQL restore
# Если зашифрован
gpg --decrypt backup.sql.gz.gpg > backup.sql.gz
# Распаковка
gunzip backup.sql.gz
# Восстановление
mysql -u root -p myapp < backup.sql
# Если есть ошибки FOREIGN KEY
mysql -u root -p myapp \
-e "SET FOREIGN_KEY_CHECKS=0; SOURCE backup.sql; \
SET FOREIGN_KEY_CHECKS=1;"Регулярное тестирование
Главное правило: бэкап, который не тестировался, не существует. Раз в месяц проверяйте:
- Восстановите последний бэкап в staging БД.
- Запустите
pg_dump --schema-onlyна оригинале и staging — сравните. - Сравните количество записей в ключевых таблицах:
SELECT count(*) FROM users;. - Запустите тесты приложения против staging — работает ли всё?
- Если что-то не сходится — разбирайтесь сразу. Не ждите реальную аварию.
- PostgreSQL Documentation — Backup and Restore. PostgreSQL Global Development Group. postgresql.org/docs/current/backup.html. 2024.
- MySQL Documentation — Backup Methods. Oracle MySQL. dev.mysql.com/doc/refman/8.0/en/backup-methods.html. 2024.
- 3-2-1 Backup Strategy. US-CERT / CISA. cisa.gov/news-events/news/data-backup-options. 2023.
