بکاپی که بازیابیاش را امتحان نکردهاید، بکاپ نیست
بیشتر حادثههای از دست رفتن داده بهخاطر نبودن بکاپ نیست؛ بهخاطر بکاپی است که ناقص، خراب یا غیرقابل بازیابی بوده و کسی تا روز حادثه امتحانش نکرده بود. دو خانوادهی اصلی بکاپ داریم:
| منطقی (mysqldump، MySQL Shell) | فیزیکی (XtraBackup، Clone، snapshot دیسک) | |
|---|---|---|
| خروجی | دستورهای SQL یا فایلهای دادهی متنی | کپی فایلهای InnoDB |
| سرعت روی ۲۰۰ گیگ | کند، بهویژه بازیابی | سریع |
| انتقال بین نسخهها | آسان | معمولاً فقط همان نسخه |
| بازیابی یک جدول | آسان | دشوارتر |
mysqldump درست
mysqldump --login-path=backup \
--single-transaction --routines --events --triggers \
--source-data=2 --set-gtid-purged=AUTO \
--default-character-set=utf8mb4 --hex-blob \
--databases carpet_factory \
| gzip > /backup/carpet_factory_$(date +%F).sql.gz
# بازیابی
gunzip < /backup/carpet_factory_2026-10-01.sql.gz | mysql --login-path=admin
--single-transaction یک snapshot سازگار با REPEATABLE READ میگیرد و جدولهای InnoDB را قفل نمیکند؛ سایت در طول بکاپ کار میکند. --source-data=2 (جایگزین --master-data از 8.0.26) مختصات binlog را بهصورت کامنت در فایل مینویسد که در درس بعد برای بازیابی لحظهای لازم است.
CREATE USER 'backup'@'localhost' IDENTIFIED BY 'Backup-Secret';
GRANT SELECT, SHOW VIEW, TRIGGER, EVENT, LOCK TABLES, RELOAD,
PROCESS, REPLICATION CLIENT, BACKUP_ADMIN ON *.* TO 'backup'@'localhost';
MySQL Shell: بکاپ منطقی موازی
ابزار mysqlsh بکاپ را با چند thread و فشردهسازی zstd میگیرد و بازیابیاش چند برابر سریعتر از اجرای یک فایل SQL بزرگ است:
// mysqlsh backup@localhost --js
util.dumpSchemas(["carpet_factory"], "/backup/shell/2026-10-01",
{threads: 8, compression: "zstd"})
util.dumpInstance("/backup/shell/full-2026-10-01", {threads: 8})
// روی سرور مقصد (local_infile باید ON باشد)
util.loadDump("/backup/shell/2026-10-01", {threads: 8, dryRun: true})
util.loadDump("/backup/shell/2026-10-01", {threads: 8})
برنامهی نگهداری
قاعدهی 3-2-1: سه نسخه، روی دو رسانهی مختلف، یکی بیرون از سرور. بکاپ شبانه با cron، نگهداری ۱۴ روزه با find /backup -name '*.sql.gz' -mtime +14 -delete و هر ماه یک بازیابی آزمایشی روی سرور جداگانه که با یک کوئری شمارش ردیفها تأیید شود.
نکتههایی که کمتر کسی میداند
- mysqldump بدون
--single-transactionبهطور پیشفرض--lock-tablesمیزند؛ یعنی در طول بکاپ هیچ سفارشی ثبت نمیشود. - اگر وسط dump یک
ALTER TABLEاجرا شود، snapshot شکسته میشود و خطایTable definition has changedیا جدول ناقص میگیرید؛ مایگریشن و بکاپ را همزمان نگذارید. - خطای
Access denied; you need the PROCESS privilegeدر نسخههای جدید با--no-tablespacesبرطرف میشود اگر نمیخواهید PROCESS بدهید. - dumpی که DEFINER آن کاربری ناموجود است، بعد از بازیابی تریگر و View را با ERROR 1449 از کار میاندازد؛ در MySQL Shell گزینهی
compatibility: ["strip_definers"]این را حل میکند. - برای بارگذاری اولیهی یک سرور تازه،
ALTER INSTANCE DISABLE INNODB REDO_LOG;سرعت را چند برابر میکند؛ فقط برای همان لحظه و هرگز روی سرور در حال سرویس. - هنگام وارد کردن dump در سروری که GTID اجراشده دارد،
--set-gtid-purged=OFFبگیرید وگرنه بازیابی با خطای GTID_PURGED متوقف میشود.