بکاپ خودکار MySQL روی فضای ابری یکی از بنیادی‌ترین اجزای استراتژی Disaster Recovery در هر پروژه‌ی جدی است که بر RPO (Recovery Point Objective)، RTO (Recovery Time Objective) و پیوستگی کسب‌وکار اثر می‌گذارد. در محیط‌های Production، بکاپ سنتی روی همان سرور، در برابر حمله‌ی Ransomware، خرابی سخت‌افزار و خطای انسانی محافظت نمی‌کند. ذخیره‌سازی ابری، با ویژگی‌هایی مانند Immutability، Versioning، Geo-Redundancy و Object Lock، لایه‌ی دفاعی مهمی فراهم می‌کند. اما پیاده‌سازی مؤثر، نیازمند درک عمیق از MySQL Backup Types، ابزارهای Percona XtraBackup و mysqldump، رمزنگاری، Binlog و استراتژی Restore است. در این راهنما، فرآیند مهندسی بکاپ خودکار MySQL روی فضای ابری، از استراتژی تا پیاده‌سازی و اعتبارسنجی، بررسی می‌شود.

در یکی از پروژه‌های سازمانی، سرور MySQL پس از یک حمله‌ی Ransomware رمزنگاری شد. بکاپ‌ها روی همان سرور ذخیره می‌شدند و از دست رفتند. سازمان مجبور شد ۴۸ ساعت داده‌ی ازدست‌رفته را بازسازی کند. اگر بکاپ ابری با Object Lock وجود داشت، این خسارت قابل پیشگیری بود.

چرا بکاپ ابری ضروری است

بکاپ ابری چند مزیت حیاتی دارد:

  • جداسازی فیزیکی: بکاپ خارج از سرور اصلی.
  • مقاومت در برابر Ransomware: با Object Lock و Immutability.
  • Geo-Redundancy: ذخیره‌سازی در چند منطقه.
  • Versioning: نگهداری نسخه‌های تاریخی.
  • مقیاس‌پذیری: بدون محدودیت فضا.
  • دسترسی از هر مکان: برای بازیابی سریع.
  • انطباق: با الزامات GDPR، HIPAA و SOC 2.

RPO و RTO

دو معیار کلیدی در استراتژی بکاپ:

  • RPO (Recovery Point Objective): حداکثر داده‌ی قابل از دست دادن.
  • RTO (Recovery Time Objective): حداکثر زمان قابل قبول برای بازیابی.
سناریو RPO RTO روش
وبلاگ شخصی ۲۴ ساعت چند ساعت Daily Dump
فروشگاه کوچک ۶ ساعت ۱ ساعت Daily Dump + Binlog
فروشگاه متوسط ۱ ساعت ۳۰ دقیقه XtraBackup + Binlog
سازمانی ۵ دقیقه ۱۵ دقیقه Replication + Binlog
مالی/حیاتی ثانیه دقیقه Sync Replication + Multi-Region

انواع بکاپ MySQL

۱. Logical Backup

Logical Backup با mysqldump انجام می‌شود و خروجی آن فایل SQL است. مزایا:

  • قابل انتقال بین نسخه‌ها و سیستم‌عامل‌ها.
  • قابل ویرایش و بازبینی.
  • مناسب برای دیتابیس‌های کوچک و متوسط.

معایب:

  • کند در دیتابیس‌های بزرگ.
  • Lock جدول در برخی تنظیمات.
  • حجم بالاتر.
mysqldump --single-transaction --routines --triggers 
  --hex-blob --default-character-set=utf8mb4 
  -u user -p database | gzip > backup-$(date +%Y%m%d).sql.gz

۲. Physical Backup

Physical Backup با Percona XtraBackup یا MySQL Enterprise Backup انجام می‌شود و کپی مستقیم فایل‌های InnoDB است. مزایا:

  • سریع در دیتابیس‌های بزرگ.
  • بدون Lock (Hot Backup).
  • مناسب برای Production.
xtrabackup --backup --target-dir=/backup/$(date +%Y%m%d) 
  --user=root --password=xxx

xtrabackup --prepare --target-dir=/backup/$(date +%Y%m%d)

۳. Snapshot Backup

Snapshot در سطح فایل‌سیستم یا Volume (مانند LVM، ZFS، AWS EBS). مزایا:

  • بسیار سریع.
  • کمترین تأثیر بر Performance.
  • مناسب برای دیتابیس‌های بزرگ.

معایب:

  • وابسته به زیرساخت.
  • نیاز به Consistency در زمان Snapshot.

۴. Binlog Backup

Binlog تمام تغییرات را ثبت می‌کند و برای Point-in-Time Recovery ضروری است.

# my.cnf
[mysqld]
log_bin = /var/log/mysql/mysql-bin.log
expire_logs_days = 7
max_binlog_size = 500M
binlog_format = ROW

ابزارهای بکاپ

ابزار نوع مناسب برای
mysqldump Logical دیتابیس کوچک
mysqlpump Logical Parallel Dump
Percona XtraBackup Physical Production
MySQL Enterprise Backup Physical Enterprise
mydumper Logical Parallel Dump
rclone Sync آپلود به ابر
aws-cli Sync S3
gsutil Sync GCS
azcopy Sync Azure Blob

انتخاب فضای ابری

سرویس ویژگی کلیدی مناسب برای
AWS S3 Object Lock، Versioning، Glacier همه
Google Cloud Storage Object Lifecycle، Bucket Lock همه
Azure Blob Immutable Blob، Soft Delete Enterprise
Backblaze B2 ارزان، Object Lock بودجه محدود
Wasabi ارزان، Immutability بکاپ حجیم
Cloudflare R2 بدون Egress Fee هزینه‌ی بهینه

نکته‌ی مهم: استفاده از Object Lock (WORM) و Versioning، برای جلوگیری از حذف بکاپ توسط Ransomware ضروری است.

رمزنگاری بکاپ

بکاپ باید در حال انتقال (In Transit) و در حالت سکون (At Rest) رمزنگاری شود:

۱. رمزنگاری In Transit

# انتقال با HTTPS
aws s3 cp backup.sql.gz s3://my-backup-bucket/ --sse AES256

# استفاده از rclone با TLS
rclone copy backup.sql.gz remote:my-backup-bucket

۲. رمزنگاری At Rest

# رمزنگاری با GPG
gpg --symmetric --cipher-algo AES256 backup.sql.gz

# رمزنگاری با openssl
openssl enc -aes-256-cbc -salt -pbkdf2 
  -in backup.sql.gz -out backup.sql.gz.enc 
  -pass file:/etc/backup.key

# رمزنگاری در S3
aws s3 cp backup.sql.gz.enc s3://my-backup-bucket/ 
  --sse-kms-key-id alias/backup-key

۳. مدیریت کلید

  • AWS KMS: مدیریت متمرکز کلید.
  • HashiCorp Vault: مدیریت Secret.
  • Key Rotation: تغییر دوره‌ای کلید.
  • Separation of Duties: کلید جدا از بکاپ.

خودکارسازی با Cron و Systemd

اسکریپت بکاپ کامل

#!/bin/bash
set -euo pipefail

# تنظیمات
DB_NAME="wordpress"
DB_USER="backup_user"
DB_PASS="$(cat /etc/mysql/backup.pass)"
BACKUP_DIR="/var/backups/mysql"
DATE=$(date +%Y%m%d-%H%M%S)
BACKUP_FILE="${BACKUP_DIR}/${DB_NAME}-${DATE}.sql.gz"
ENCRYPTED_FILE="${BACKUP_FILE}.enc"
S3_BUCKET="s3://my-backup-bucket/mysql"

# ایجاد دایرکتوری
mkdir -p "${BACKUP_DIR}"

# بکاپ Logical با mysqldump
mysqldump --single-transaction 
  --routines --triggers --hex-blob 
  --default-character-set=utf8mb4 
  -u"${DB_USER}" -p"${DB_PASS}" 
  "${DB_NAME}" | gzip > "${BACKUP_FILE}"

# رمزنگاری
openssl enc -aes-256-cbc -salt -pbkdf2 
  -in "${BACKUP_FILE}" -out "${ENCRYPTED_FILE}" 
  -pass file:/etc/backup.key

# آپلود به S3 با Object Lock
aws s3 cp "${ENCRYPTED_FILE}" "${S3_BUCKET}/${DATE}.sql.gz.enc" 
  --storage-class STANDARD_IA 
  --sse AES256

# پاک‌سازی محلی
rm -f "${BACKUP_FILE}" "${ENCRYPTED_FILE}"

# لاگ
echo "$(date): Backup completed: ${S3_BUCKET}/${DATE}.sql.gz.enc" 
  >> /var/log/mysql-backup.log

Cron Job

# /etc/cron.d/mysql-backup
0 2 * * * root /usr/local/bin/mysql-backup.sh >> /var/log/mysql-backup.log 2>&1

Systemd Timer (جایگزین مدرن)

# /etc/systemd/system/mysql-backup.service
[Unit]
Description=MySQL Cloud Backup
After=network.target

[Service]
Type=oneshot
ExecStart=/usr/local/bin/mysql-backup.sh
User=root

# /etc/systemd/system/mysql-backup.timer
[Unit]
Description=Daily MySQL Backup

[Timer]
OnCalendar=daily
Persistent=true
RandomizedDelaySec=1h

[Install]
WantedBy=timers.target

Point-in-Time Recovery با Binlog

Point-in-Time Recovery (PITR) امکان بازیابی به هر لحظه را فراهم می‌کند:

# ۱. بازیابی آخرین بکاپ کامل
gunzip < backup.sql.gz | mysql -u root -p database

# ۲. اعمال Binlog تا زمان مورد نظر
mysqlbinlog --start-datetime="2024-01-15 00:00:00" 
  --stop-datetime="2024-01-15 14:30:00" 
  /var/log/mysql/mysql-bin.000123 | mysql -u root -p database

نکته‌ی مهم: برای PITR، باید Binlog نیز روی فضای ابری ذخیره شود.

# آپلود Binlog به S3
aws s3 sync /var/log/mysql/ s3://my-backup-bucket/binlog/ 
  --exclude "*" --include "mysql-bin.*"

Retention Policy

Retention Policy تعیین می‌کند که هر بکاپ چه مدت نگهداری شود:

نوع بکاپ مدت نگهداری ذخیره‌سازی
Daily ۳۰ روز Standard
Weekly ۳ ماه Standard-IA
Monthly ۱ سال Glacier
Yearly ۷ سال Glacier Deep Archive
Binlog ۷ روز Standard

Lifecycle Policy در S3

{
  "Rules": [
    {
      "Id": "BackupLifecycle",
      "Status": "Enabled",
      "Transitions": [
        { "Days": 30, "StorageClass": "STANDARD_IA" },
        { "Days": 90, "StorageClass": "GLACIER" }
      ],
      "Expiration": { "Days": 365 }
    }
  ]
}

مانیتورینگ و Alerting

بکاپ بدون مانیتورینگ، یک توهم امنیت است:

# بررسی وجود بکاپ امروز
TODAY=$(date +%Y-%m-%d)
if ! aws s3 ls "s3://my-backup-bucket/mysql/" | grep -q "${TODAY}"; then
  echo "ALERT: No backup found for ${TODAY}" | mail -s "Backup Failed" admin@example.com
fi

# بررسی اندازه‌ی بکاپ
LATEST_SIZE=$(aws s3 ls "s3://my-backup-bucket/mysql/" --recursive 
  | sort | tail -1 | awk "{print $3}")

if [ "${LATEST_SIZE}" -lt 1000000 ]; then
  echo "ALERT: Backup size too small" | mail -s "Backup Suspicious" admin@example.com
fi

ابزارهای Monitoring

  • Prometheus + Grafana: Dashboard متمرکز.
  • Sentry: Error Tracking.
  • Slack/Telegram: Alerting.
  • PagerDuty: Incident Management.
  • Healthchecks.io: Cron Monitoring.

تست بازیابی

بکاپی که تست نشود، بکاپ نیست:

  1. تست فصلی: بازیابی کامل در محیط Staging.
  2. تست خودکار: اسکریپت بازیابی در محیط ایزوله.
  3. اندازه‌گیری RTO: زمان واقعی بازیابی.
  4. بررسی Integrity: اجرای CHECK TABLE.
  5. مقایسه‌ی رکوردها: با Source.
#!/bin/bash
# restore-test.sh
set -euo pipefail

TEST_DB="restore_test_$(date +%s)"
S3_PATH="s3://my-backup-bucket/mysql/$(date +%Y-%m-%d).sql.gz.enc"

# دانلود
aws s3 cp "${S3_PATH}" /tmp/restore.sql.gz.enc

# رمزگشایی
openssl enc -d -aes-256-cbc -pbkdf2 
  -in /tmp/restore.sql.gz.enc -out /tmp/restore.sql.gz 
  -pass file:/etc/backup.key

# بازیابی در دیتابیس تست
mysql -u root -p -e "CREATE DATABASE ${TEST_DB}"
gunzip < /tmp/restore.sql.gz | mysql -u root -p "${TEST_DB}"

# بررسی
mysql -u root -p "${TEST_DB}" -e "CHECK TABLE wp_posts"

# پاک‌سازی
mysql -u root -p -e "DROP DATABASE ${TEST_DB}"
rm -f /tmp/restore.sql.gz*

echo "$(date): Restore test passed"

پرسش‌های پرتکرار

چند وقت یک‌بار باید بکاپ گرفت؟

بر اساس RPO. برای سایت‌های معمولی، روزانه. برای فروشگاه‌ها، هر ۶ ساعت. برای سازمانی، هر ساعت یا Binlog.

آیا بکاپ ابری امن است؟

با رمزنگاری At Rest و In Transit، Object Lock و Versioning، بله.

آیا mysqldump برای دیتابیس‌های بزرگ مناسب است؟

برای دیتابیس‌های بیشتر از ۱۰ گیگابایت، Percona XtraBackup توصیه می‌شود.

آیا بکاپ باید روی همان ابر باشد یا ابر جداگانه؟

برای مقاومت بیشتر، Multi-Cloud (مثلاً S3 + Backblaze) توصیه می‌شود.

چگونه از Object Lock استفاده کنیم؟

با فعال‌سازی Object Lock در S3 و تعیین Retention Mode (Compliance یا Governance).

آیا Binlog برای همه‌ی سناریوها لازم است؟

برای PITR بله. برای بکاپ روزانه بدون PITR، اختیاری است.

چند بار باید تست بازیابی انجام شود؟

حداقل فصلی یک‌بار. برای سیستم‌های حیاتی، ماهانه.

اشتباهات رایج

اشتباه علت راه‌حل
بکاپ روی همان سرور سادگی بکاپ ابری
عدم رمزنگاری ناآشنایی GPG یا KMS
عدم Object Lock غفلت از Ransomware Object Lock در S3
عدم تست بازیابی فرض موفقیت تست فصلی
عدم مانیتورینگ فرض اجرای Cron Alerting
Retention نامناسب هزینه باور غلط Lifecycle Policy
عدم Binlog عدم نیاز به PITR فعال‌سازی Binlog
مدیریت کلید نامناسب کلید همراه بکاپ کلید جدا + Vault/KMS

ملاحظات پیشرفته

در سطح معماری، استراتژی بکاپ ابری نیازمند رویکرد جامع است:

۱. Multi-Cloud Backup: توزیع بکاپ بین چند ابر.

۲. Immutable Storage: با Object Lock در Compliance Mode.

۳. Cross-Region Replication: برای Geo-Redundancy.

۴. Automated Restore Testing: با CI/CD Pipeline.

۵. Encryption Key Management: با KMS و Vault.

۶. Compliance: با GDPR، HIPAA، SOC 2.

۷. Disaster Recovery Plan: مستندسازی و تمرین.

۸. Zero Trust: دسترسی محدود به بکاپ.

برای مطالعه‌ی بیشتر، پست‌های پشتیبان گیری از mysql، پشتیبان‌گیری امن از دیتابیس، پشتیبان‌گیری ابری چه مزایایی دارد، چگونه از دیتابیس وردپرس بکاپ بگیریم، پشتیبان‌گیری خودکار چگونه انجام می‌شود، چرا بیشتر سایت‌ها در روز بحران نمی‌توانند از بکاپ خودشان استفاده کنند و چند نسخه بکاپ باید نگهداری کنیم مراجع کاملی هستند.

نتیجه

بکاپ خودکار MySQL روی فضای ابری یک فرآیند مهندسی چندلایه است که با تعریف RPO و RTO، انتخاب ابزار مناسب، رمزنگاری، خودکارسازی، مانیتورینگ و تست بازیابی انجام می‌شود. Object Lock و Immutability، مقاومت در برابر Ransomware را فراهم می‌کنند و Binlog، امکان PITR را می‌دهد. موفقیت در این حوزه، نتیجه‌ی هماهنگی بین MySQL، زیرساخت ابری و استراتژی Disaster Recovery است.

💡 اگر تجربه‌ای در بکاپ خودکار MySQL روی فضای ابری داشته‌اید، برای ما جالب است بدانیم کدام بخش بیشترین چالش را ایجاد کرد: رمزنگاری، خودکارسازی یا تست بازیابی. تجربه‌ی خودتان را در دیدگاه‌ها بنویسید.