MySQL وتصميم قواعد البيانات

النسخ الاحتياطي والاسترداد

13 دقيقة الدرس 33 من 40

النسخ الاحتياطي والاسترداد

النسخ الاحتياطية لقاعدة البيانات هي شبكة أمانك ضد فقدان البيانات من فشل الأجهزة أو أخطاء البرمجيات أو الخطأ البشري أو الانتهاكات الأمنية. في هذا الدرس، ستتعلم استراتيجيات النسخ الاحتياطي الشاملة، وإجراءات الاستعادة، والاسترداد في نقطة زمنية، وتخطيط استرداد الكوارث.

لماذا النسخ الاحتياطي مهم

فهم أهمية النسخ الاحتياطية يساعدك على أخذها بجدية:

سيناريوهات شائعة تتطلب استعادة النسخ الاحتياطي: ✗ فشل الأجهزة (تعطل القرص، فشل الخادم) ✗ حذف البيانات بالخطأ (DROP TABLE, DELETE بدون WHERE) ✗ أخطاء البرمجيات التي تفسد البيانات ✗ هجمات برامج الفدية ✗ الكوارث الطبيعية ✗ الخطأ البشري أثناء الصيانة ✗ تلف قاعدة البيانات ✗ الانتقال إلى خادم جديد قاعدة أفضل ممارسات النسخ الاحتياطي: "إذا لم يكن لديك 3 نسخ على الأقل من بياناتك في تنسيقين مختلفين مع نسخة واحدة خارج الموقع، فليس لديك نسخة احتياطية." - قاعدة النسخ الاحتياطي 3-2-1
حاسم: النسخ الاحتياطية مفيدة فقط إذا كان بإمكانك استعادتها. اختبر بانتظام عملية استعادة النسخ الاحتياطي لضمان صحة واكتمال النسخ الاحتياطية.

أنواع النسخ الاحتياطية

فهم أنواع النسخ الاحتياطية المختلفة يساعدك على اختيار الاستراتيجية الصحيحة:

1. النسخ الاحتياطي الكامل: - نسخة كاملة من قاعدة البيانات بأكملها - الإيجابيات: بسيط، استعادة سريعة - السلبيات: حجم كبير، يستغرق وقتاً طويلاً - التكرار: أسبوعي أو شهري 2. النسخ الاحتياطي التزايدي: - التغييرات فقط منذ آخر نسخة احتياطية - الإيجابيات: سريع، حجم صغير - السلبيات: استعادة أبطأ (تحتاج جميع الزيادات) - التكرار: يومي أو كل ساعة 3. النسخ الاحتياطي التفاضلي: - التغييرات منذ آخر نسخة احتياطية كاملة - الإيجابيات: استعادة أسرع من التزايدي - السلبيات: أكبر من التزايدي - التكرار: يومي 4. النسخ الاحتياطي المنطقي: - عبارات SQL لإعادة إنشاء البيانات - مثال: مخرجات mysqldump - الإيجابيات: قابل للقراءة، محمول - السلبيات: أبطأ لقواعد البيانات الكبيرة 5. النسخ الاحتياطي المادي: - نسخ من ملفات قاعدة البيانات - مثال: نسخ نظام الملفات - الإيجابيات: سريع لقواعد البيانات الكبيرة - السلبيات: خاص بالمنصة

استخدام mysqldump (النسخ الاحتياطي المنطقي)

mysqldump هي أداة النسخ الاحتياطي الأكثر شيوعاً لـ MySQL. تنشئ عبارات SQL تعيد إنشاء قاعدة بياناتك:

أوامر mysqldump الأساسية: # نسخ احتياطي لقاعدة بيانات واحدة mysqldump -u root -p database_name > backup.sql # نسخ احتياطي لعدة قواعد بيانات mysqldump -u root -p --databases db1 db2 db3 > backup.sql # نسخ احتياطي لجميع قواعد البيانات mysqldump -u root -p --all-databases > all_backup.sql # نسخ احتياطي لجداول محددة mysqldump -u root -p database_name table1 table2 > tables_backup.sql # نسخ احتياطي مع الضغط mysqldump -u root -p database_name | gzip > backup.sql.gz # نسخ احتياطي مع طابع زمني في اسم الملف mysqldump -u root -p database_name > backup_$(date +%Y%m%d_%H%M%S).sql
نصيحة: اضغط دائماً النسخ الاحتياطية الكبيرة لتوفير مساحة القرص. استخدم gzip لنسبة ضغط جيدة أو pigz للضغط المتوازي على الأنظمة متعددة النوى.

خيارات mysqldump المتقدمة

حسّن mysqldump لسيناريوهات مختلفة:

أمر نسخ احتياطي جاهز للإنتاج: mysqldump -u backup_user -p \ --single-transaction \ # لقطة متسقة لـ InnoDB --quick \ # لا تخزن الاستعلام مؤقتاً، احفظ مباشرة --lock-tables=false \ # لا تقفل الجداول --routines \ # تضمين الإجراءات/الدوال المخزنة --triggers \ # تضمين المشغلات --events \ # تضمين الأحداث المجدولة --flush-logs \ # مسح السجلات الثنائية --master-data=2 \ # تسجيل موضع السجل الثنائي --hex-blob \ # استخدام تنسيق hex لأعمدة BLOB --default-character-set=utf8mb4 \ database_name > backup.sql نسخ احتياطي للبنية فقط (بدون بيانات): mysqldump -u root -p --no-data database_name > schema.sql نسخ احتياطي للبيانات فقط (بدون بنية): mysqldump -u root -p --no-create-info database_name > data.sql تخطي جداول محددة: mysqldump -u root -p database_name \ --ignore-table=database_name.logs \ --ignore-table=database_name.cache > backup.sql

الاستعادة من نسخة احتياطية mysqldump

الاستعادة مباشرة مع نسخ احتياطية mysqldump:

الاستعادة الأساسية: # الاستعادة إلى قاعدة بيانات موجودة mysql -u root -p database_name < backup.sql # إنشاء قاعدة بيانات والاستعادة mysql -u root -p -e "CREATE DATABASE database_name" mysql -u root -p database_name < backup.sql # استعادة نسخة احتياطية مضغوطة gunzip < backup.sql.gz | mysql -u root -p database_name # الاستعادة مع مراقبة التقدم pv backup.sql | mysql -u root -p database_name استعادة جميع قواعد البيانات: mysql -u root -p < all_backup.sql استعادة جدول محدد: # استخراج الجدول من النسخة الاحتياطية الكاملة أولاً sed -n '/CREATE TABLE `users`/,/UNLOCK TABLES/p' backup.sql > users_table.sql mysql -u root -p database_name < users_table.sql
مهم: استعد دائماً إلى بيئة اختبار أولاً للتحقق من سلامة النسخ الاحتياطي قبل الاستعادة إلى الإنتاج.

نص النسخ الاحتياطي التلقائي

أنشئ نص نسخ احتياطي تلقائي قوي للاستخدام في الإنتاج:

backup_mysql.sh: #!/bin/bash # التكوين DB_USER="backup_user" DB_PASS="SecureBackupPass2024!" DB_HOST="localhost" BACKUP_DIR="/var/backups/mysql" RETENTION_DAYS=30 DATE=$(date +%Y%m%d_%H%M%S) # إنشاء دليل النسخ الاحتياطي mkdir -p $BACKUP_DIR # الحصول على قائمة قواعد البيانات (استبعاد قواعد بيانات النظام) DATABASES=$(mysql -u $DB_USER -p$DB_PASS -h $DB_HOST -e "SHOW DATABASES;" | \ grep -Ev "(Database|information_schema|performance_schema|mysql|sys)") # نسخ احتياطي لكل قاعدة بيانات for DB in $DATABASES; do echo "Backing up database: $DB" mysqldump -u $DB_USER -p$DB_PASS -h $DB_HOST \ --single-transaction \ --routines \ --triggers \ --events \ $DB | gzip > "$BACKUP_DIR/${DB}_$DATE.sql.gz" # التحقق من نجاح النسخ الاحتياطي if [ $? -eq 0 ]; then echo "✓ Successfully backed up $DB" else echo "✗ Failed to backup $DB" >&2 fi done # حذف النسخ الاحتياطية القديمة find $BACKUP_DIR -type f -name "*.sql.gz" -mtime +$RETENTION_DAYS -delete echo "Backup completed: $(date)"
الأتمتة: جدول هذا النص مع cron للنسخ الاحتياطية اليومية: 0 2 * * * /path/to/backup_mysql.sh >> /var/log/mysql_backup.log 2>&1 يعمل هذا يومياً في الساعة 2 صباحاً ويسجل المخرجات.

نسخ احتياطية السجل الثنائي للاسترداد في نقطة زمنية

تسمح لك السجلات الثنائية بالاسترداد إلى لحظة محددة في الوقت:

تمكين التسجيل الثنائي (my.cnf): [mysqld] log-bin = /var/log/mysql/mysql-bin expire_logs_days = 7 max_binlog_size = 100M binlog_format = ROW عرض السجلات الثنائية: SHOW BINARY LOGS; SHOW MASTER STATUS; نسخ احتياطي للسجلات الثنائية: # مسح وإنشاء سجل ثنائي جديد mysqladmin -u root -p flush-logs # نسخ السجلات الثنائية إلى موقع النسخ الاحتياطي cp /var/log/mysql/mysql-bin.* /backups/binlogs/ عملية الاسترداد في نقطة زمنية: # 1. الاستعادة من نسخة احتياطية كاملة mysql -u root -p database_name < full_backup.sql # 2. تطبيق السجلات الثنائية من وقت النسخ الاحتياطي إلى النقطة المطلوبة mysqlbinlog --start-datetime="2024-02-01 00:00:00" \ --stop-datetime="2024-02-08 14:30:00" \ /var/log/mysql/mysql-bin.000001 \ /var/log/mysql/mysql-bin.000002 | \ mysql -u root -p database_name # 3. أو استخدم الموضع بدلاً من التاريخ والوقت mysqlbinlog --start-position=120 --stop-position=332 \ mysql-bin.000003 | mysql -u root -p database_name

النسخ الاحتياطية المادية مع نسخ نظام الملفات

تنسخ النسخ الاحتياطية المادية ملفات قاعدة البيانات الفعلية - أسرع لقواعد البيانات الكبيرة جداً:

نسخ احتياطي بارد (الخادم متوقف): # 1. إيقاف MySQL sudo systemctl stop mysql # 2. نسخ دليل البيانات sudo cp -R /var/lib/mysql /backup/mysql_data_backup # 3. تشغيل MySQL sudo systemctl start mysql نسخ احتياطي ساخن مع Percona XtraBackup: # قم بتثبيت Percona XtraBackup أولاً # نسخ احتياطي كامل xtrabackup --backup --target-dir=/backup/full # نسخ احتياطي تزايدي xtrabackup --backup \ --target-dir=/backup/inc1 \ --incremental-basedir=/backup/full # تحضير النسخة الاحتياطية للاستعادة xtrabackup --prepare --target-dir=/backup/full # الاستعادة sudo systemctl stop mysql sudo rm -rf /var/lib/mysql/* xtrabackup --copy-back --target-dir=/backup/full sudo chown -R mysql:mysql /var/lib/mysql sudo systemctl start mysql
تحذير: لا تقم أبداً بنسخ احتياطي بارد على خوادم الإنتاج خلال ساعات العمل. جدول دائماً أثناء نوافذ الصيانة.

التحقق من النسخ الاحتياطي

تحقق دائماً من سلامة النسخ الاحتياطي:

طرق التحقق: # 1. التحقق من حجم الملف (لا ينبغي أن يكون 0 أو صغيراً بشكل مريب) ls -lh backup.sql.gz # 2. اختبار فك الضغط gunzip -t backup.sql.gz echo $? # يجب أن يعيد 0 للنجاح # 3. إجراء استعادة اختبار mysql -u root -p test_restore_db < backup.sql # 4. التحقق من عدد الجداول وعدد الصفوف mysql -u root -p -e "USE test_restore_db; \ SELECT COUNT(*) FROM information_schema.TABLES \ WHERE TABLE_SCHEMA = 'test_restore_db';" # 5. نص التحقق من المجموع الاختباري #!/bin/bash DB="production_db" BACKUP="backup.sql" # الحصول على المجاميع الاختبارية من قاعدة البيانات الحية mysql -u root -p $DB -e "CHECKSUM TABLE users, orders, products" > live_checksums.txt # استعادة النسخة الاحتياطية إلى قاعدة بيانات اختبار mysql -u root -p test_db < $BACKUP # الحصول على المجاميع الاختبارية من قاعدة البيانات المستعادة mysql -u root -p test_db -e "CHECKSUM TABLE users, orders, products" > backup_checksums.txt # المقارنة diff live_checksums.txt backup_checksums.txt

النسخ الاحتياطي خارج الموقع والسحابة

خزّن النسخ الاحتياطية في مواقع متعددة لاسترداد الكوارث:

1. النسخ إلى خادم بعيد عبر rsync: rsync -avz --delete /var/backups/mysql/ \ user@remote-server:/backups/mysql/ 2. التحميل إلى AWS S3: # قم بتثبيت AWS CLI أولاً aws s3 sync /var/backups/mysql/ s3://my-backup-bucket/mysql/ 3. نص نسخ احتياطي تلقائي خارج الموقع: #!/bin/bash BACKUP_FILE="/var/backups/mysql/backup_$(date +%Y%m%d).sql.gz" S3_BUCKET="s3://company-backups/mysql/" # إنشاء نسخة احتياطية mysqldump -u root -p --all-databases | gzip > $BACKUP_FILE # التحميل إلى S3 aws s3 cp $BACKUP_FILE $S3_BUCKET # التحميل إلى خادم بعيد scp $BACKUP_FILE backup@remote-server:/backups/ # التحقق من التحميل if [ $? -eq 0 ]; then echo "✓ Backup uploaded successfully" else echo "✗ Backup upload failed!" | mail -s "Backup Failed" admin@company.com fi
أفضل ممارسة: شفّر النسخ الاحتياطية قبل تحميلها إلى التخزين السحابي. استخدم تشفير GPG أو OpenSSL مع نظام إدارة مفاتيح آمن.

النسخ الاحتياطية المشفرة

احمِ البيانات الحساسة في النسخ الاحتياطية بالتشفير:

استخدام OpenSSL: # نسخ احتياطي مع التشفير mysqldump -u root -p database_name | \ openssl enc -aes-256-cbc -salt -pbkdf2 -out backup_encrypted.sql.enc # الاستعادة من نسخة احتياطية مشفرة openssl enc -aes-256-cbc -d -pbkdf2 -in backup_encrypted.sql.enc | \ mysql -u root -p database_name استخدام GPG: # نسخ احتياطي مع تشفير GPG mysqldump -u root -p database_name | \ gzip | gpg --symmetric --cipher-algo AES256 -o backup.sql.gz.gpg # الاستعادة من نسخة احتياطية مشفرة GPG gpg --decrypt backup.sql.gz.gpg | gunzip | \ mysql -u root -p database_name

خطة استرداد الكوارث

احصل على خطة استرداد موثقة لسيناريوهات الفشل المختلفة:

هدف وقت الاسترداد (RTO): الحد الأقصى المقبول لوقت التوقف مثال: 4 ساعات هدف نقطة الاسترداد (RPO): الحد الأقصى المقبول لفقدان البيانات مثال: ساعة واحدة من البيانات قائمة استرداد الكوارث: 1. تحديد نوع الفشل □ فشل الأجهزة □ تلف البيانات □ حذف عرضي □ انتهاك أمني 2. تقييم الضرر □ ما البيانات المتأثرة؟ □ متى حدثت المشكلة؟ □ هل النسخة الاحتياطية الحديثة متاحة؟ 3. الاستعادة من نسخة احتياطية مناسبة □ أحدث نسخة احتياطية كاملة □ تطبيق السجلات التزايدية/الثنائية □ التحقق من سلامة البيانات 4. اختبار قاعدة البيانات المستعادة □ تشغيل اختبارات التطبيق □ التحقق من البيانات الحرجة □ التحقق من التلف 5. التبديل إلى قاعدة البيانات المستعادة □ تحديث تكوين التطبيق □ إعادة توجيه حركة المرور □ مراقبة المشاكل 6. مراجعة ما بعد الحادث □ توثيق ما حدث □ تحديث إجراءات النسخ الاحتياطي □ تحسين المراقبة

مراقبة النسخ الاحتياطي والتنبيهات

راقب مهام النسخ الاحتياطي واحصل على تنبيهات عند الفشل:

نص مراقبة النسخ الاحتياطي: #!/bin/bash BACKUP_DIR="/var/backups/mysql" MAX_AGE_HOURS=26 # تنبيه إذا كانت النسخة الاحتياطية أقدم من 26 ساعة ADMIN_EMAIL="admin@company.com" # البحث عن أحدث نسخة احتياطية LATEST_BACKUP=$(find $BACKUP_DIR -type f -name "*.sql.gz" -mmin -$((MAX_AGE_HOURS*60))) if [ -z "$LATEST_BACKUP" ]; then echo "WARNING: No recent MySQL backup found!" | \ mail -s "MySQL Backup Alert" $ADMIN_EMAIL exit 1 fi # التحقق من حجم النسخة الاحتياطية (يجب أن يكون > 1MB لمعظم قواعد البيانات) BACKUP_SIZE=$(du -m "$LATEST_BACKUP" | cut -f1) if [ $BACKUP_SIZE -lt 1 ]; then echo "WARNING: MySQL backup file is suspiciously small: ${BACKUP_SIZE}MB" | \ mail -s "MySQL Backup Alert" $ADMIN_EMAIL exit 1 fi echo "✓ Backup check passed: $LATEST_BACKUP (${BACKUP_SIZE}MB)"

تمرين عملي:

السيناريو: أنشئ حل نسخ احتياطي واسترداد كامل:

  1. إجراء نسخة احتياطية كاملة لقاعدة البيانات
  2. إجراء بعض التغييرات على البيانات
  3. إجراء نسخة احتياطية تزايدية (سجل ثنائي)
  4. محاكاة فقدان البيانات (حذف جدول)
  5. الاستعادة من نسخة احتياطية كاملة
  6. تطبيق السجلات الثنائية للاسترداد إلى قبل فقدان البيانات مباشرة

الحل:

# الخطوة 1: نسخة احتياطية كاملة في الساعة 10:00 صباحاً mysqldump -u root -p --single-transaction \ --flush-logs --master-data=2 \ mydb > backup_full_10am.sql # الخطوة 2: إجراء التغييرات mysql -u root -p mydb -e "INSERT INTO orders (customer, amount) \ VALUES ('John', 150.00), ('Mary', 200.00);" # الخطوة 3: السجلات الثنائية تسجل التغييرات تلقائياً # الخطوة 4: تحدث الكارثة في الساعة 2:30 مساءً mysql -u root -p mydb -e "DROP TABLE orders;" # عرضي! # الخطوة 5: الاستعادة من نسخة احتياطية كاملة mysql -u root -p mydb < backup_full_10am.sql # الخطوة 6: تطبيق السجلات الثنائية حتى 2:29 مساءً (قبل DROP) mysqlbinlog --stop-datetime="2024-02-08 14:29:00" \ /var/log/mysql/mysql-bin.000001 | mysql -u root -p mydb # التحقق من الاسترداد mysql -u root -p mydb -e "SELECT * FROM orders;" # يجب أن يظهر طلبات John و Mary!

الملخص

في هذا الدرس، تعلمت:

  • أهمية النسخ الاحتياطية وقاعدة النسخ الاحتياطي 3-2-1
  • أنواع النسخ الاحتياطية المختلفة: كامل، تزايدي، تفاضلي، منطقي، مادي
  • استخدام mysqldump للنسخ الاحتياطية المنطقية مع خيارات متقدمة
  • إجراءات الاستعادة والتحقق
  • نصوص النسخ الاحتياطي التلقائية مع معالجة الأخطاء
  • السجلات الثنائية للاسترداد في نقطة زمنية
  • النسخ الاحتياطية المادية مع Percona XtraBackup
  • استراتيجيات النسخ الاحتياطي خارج الموقع والسحابة
  • التشفير لأمان النسخ الاحتياطي
  • تخطيط وإجراءات استرداد الكوارث
التالي: في الدرس التالي، سنستكشف استيراد وتصدير البيانات بما في ذلك LOAD DATA INFILE, SELECT INTO OUTFILE، معالجة CSV، وعمليات البيانات الضخمة.