Настройка автоматического бэкапирования базы данных по расписанию
Потеря данных из-за отсутствия бэкапов — одна из наиболее дорогостоящих ошибок в эксплуатации веб-приложений. Настройка автоматических бэкапов по расписанию — базовое требование для любого production-сервера.
Выбор инструмента
| БД | Инструмент | Формат |
|---|---|---|
| PostgreSQL | pg_dump / pg_dumpall |
SQL / custom |
| MySQL/MariaDB | mysqldump / Percona XtraBackup |
SQL / binary |
| MongoDB | mongodump |
BSON |
| Redis | BGSAVE / AOF snapshot |
RDB / AOF |
| SQLite | sqlite3 .backup |
binary |
PostgreSQL: базовая настройка
#!/bin/bash
# /opt/scripts/backup-postgres.sh
BACKUP_DIR="/var/backups/postgres"
DB_NAME="myapp_production"
DATE=$(date +%Y%m%d_%H%M%S)
FILENAME="$BACKUP_DIR/${DB_NAME}_${DATE}.dump"
mkdir -p "$BACKUP_DIR"
pg_dump -U postgres -Fc "$DB_NAME" > "$FILENAME"
# Удаление бэкапов старше 7 дней
find "$BACKUP_DIR" -name "*.dump" -mtime +7 -delete
# Проверка успешности
if [ $? -eq 0 ]; then
echo "Backup successful: $FILENAME"
else
echo "Backup FAILED" >&2
exit 1
fi
Cron-задача:
0 2 * * * /opt/scripts/backup-postgres.sh >> /var/log/backup.log 2>&1
MySQL: настройка с паролем через .my.cnf
# ~/.my.cnf (права 600)
[mysqldump]
user=backup_user
password=secret_password
mysqldump --single-transaction --routines --triggers myapp_db | \
gzip > "/var/backups/mysql/myapp_$(date +%Y%m%d_%H%M%S).sql.gz"
--single-transaction критически важен для InnoDB — создаёт консистентный снапшот без блокировки таблиц.
Ротация и хранение
Стратегия GFS (Grandfather-Father-Son):
- Ежедневные — хранятся 7 дней
- Еженедельные — хранятся 4 недели
- Ежемесячные — хранятся 12 месяцев
Реализация через logrotate или скрипт с find -mtime.
Загрузка в S3/объектное хранилище
aws s3 cp "$FILENAME" "s3://company-backups/postgres/${DB_NAME}/" \
--storage-class STANDARD_IA \
--server-side-encryption AES256
# Или через rclone для любого провайдера
rclone copy "$FILENAME" remote:backups/postgres/
Для автоматической ротации в S3 настраивается Lifecycle Policy: перевод в Glacier через 30 дней, удаление через 1 год.
Уведомления об ошибках
# Отправка уведомления в Slack при сбое
if [ $? -ne 0 ]; then
curl -X POST "$SLACK_WEBHOOK" \
-d '{"text": "CRITICAL: Database backup failed on '"$(hostname)"'"}'
fi
Альтернатива — healthcheck через Healthchecks.io или Better Uptime: скрипт пингует URL после успешного бэкапа, сервис бьёт тревогу если пинг не пришёл.
Проверка бэкапов
Бэкап без проверки восстановления — не бэкап. Еженедельный тест:
# Восстановление в тестовую БД
pg_restore -U postgres -d test_restore --clean "$FILENAME"
# Проверка количества записей
psql -U postgres -d test_restore -c "SELECT COUNT(*) FROM users;"
Срок выполнения
Настройка бэкапирования одной БД с ротацией и S3-загрузкой — 1 рабочий день.







