Workstation Logo
المنتجات
مختبرات الذكاء الاصطناعيوكلاء OpenAIوكلاء ClaudeGrok BotWorkstation CRM (WSL CRM)التسويقجميع المنتجات
حلول الذكاء الاصطناعي
محطات عمل الذكاء الاصطناعيAI SME Packagesذكاء اصطناعي خاصمجموعات GPUذكاء اصطناعي طرفيمختبر الذكاء الاصطناعي للمؤسساتالذكاء الاصطناعي حسب الصناعة
الخدمات
Platform ModernisationDigital EngineeringData Foundations & AIAutonomous Operationsاستشارات الذكاء الاصطناعيأتمتة DevOpsالأمن السيبرانيتطوير البرمجياتبناء الوكلاءإعداد MLOps
من نحن
الشركاءقصص العملاء
المقالات
الوثائق
WSL ProxyRing PromoterWSL VaultJobshoutSysOps 24/7
المدونة
اتصل بناLogin
Workstation

محطات عمل الذكاء الاصطناعي وبرمجيات الوكلاء المتعددة والبنية التحتية لوحدات GPU وحلول الوكلاء الأذكياء للشركات الحديثة.

اتصل بنا

حلول الذكاء الاصطناعي

محطات عمل الذكاء الاصطناعيAI SME Packagesذكاء اصطناعي خاصمجموعات GPUذكاء اصطناعي طرفيمختبر الذكاء الاصطناعي للمؤسساتالذكاء الاصطناعي حسب الصناعة

المنتجات

جميع المنتجاتWSL CRM و ERPالتسويقوكلاء OpenAIWSL ProxyRing PromoterWSL VaultJobshoutSysOps 24/7

الشركة

من نحنلماذا Workstationالشركاءقصص العملاءالأسعاراتصل

الموارد

المقالاتالتوثيقالمدونةبحثخريطة الموقع
مكتب المملكة المتحدة
77-79 Marlowes, Hemel Hempstead HP1 1LFالاتجاهات - اسلك المخرج 20 من الطريق M25 في لندن الخارجيةرقم الشركة: 11641870الاثنين - الجمعة: 9:00 ص - 6:00 م بتوقيت GMT
+44 7515 356 146
مكتب بلجيكا
Workstation SRL, Rue Vanderkindere 34, 1180 Uccle, BrusselsBE 0751.518.683الاثنين - الجمعة: 9:00 ص - 6:00 م بتوقيت CET
+32 492 45 67 46
مكتب الهند
#159 Sector 9, Pocket 1, DDA Flats, 110077 Dwarka, New Delhi
+91 98881 98841

© 2026 Workstation AI. جميع الحقوق محفوظة.

الخصوصيةملفات تعريف الارتباطشروط الخدمةخريطة الموقع الإلكتروني

Loading blog...

Home / Blog
DatabaseDevOpsKubernetesBackend

استراتيجيات النسخ الاحتياطي لقاعدة بيانات الإنتاج التي تعمل بالفعل: MySQL وPostgreSQL

استراتيجيات النسخ الاحتياطي والاسترداد المثبتة لـ MySQL وPostgreSQL في الإنتاج

Balinder Walia12 أبريل 202631 min read

فقدان بيانات الإنتاج هو نوع من الحوادث التي تنهي الوظائف، وتغلق الشركات، وتتصدر الصفحة الأولى من Hacker News لجميع الأسباب الخاطئة. ومع ذلك، تتعامل معظم الفرق مع النسخ الاحتياطية لقاعدة البيانات كفكرة لاحقة - وهي مهمة cron أنشأها شخص ما قبل عامين ولم يتحقق أحد من صحتها منذ ذلك الحين. توضح هذه المقالة إستراتيجيات النسخ الاحتياطي التي تم اختبارها في المعركة لـ MySQL وPostgreSQL والتي تم إثبات كفاءتها في بيئات الإنتاج التي تتراوح من مجموعات k3s أحادية العقدة إلى عمليات النشر السحابية متعددة المناطق التي تعالج ملايين المعاملات يوميًا.

سنغطي النطاق الكامل: طرق النسخ الاحتياطي المنطقية والمادية، والاسترداد في الوقت المناسب، والجدولة الآلية، وأهداف التخزين السحابي، والتشفير، والتحقق، وأساليب Kubernetes الأصلية، وتخطيط التعافي من الكوارث الذي يربط كل ذلك معًا. تأتي كل توصية مصحوبة بتكوين محدد ورمز يمكنك تكييفه مع بيئتك.

فهم أنواع النسخ الاحتياطي

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

النسخ الاحتياطي الكامليلتقطقاعدة البيانات بأكملها في وقت واحد. إنه الأسهل في التفكير والأسرع في الاستعادة، ولكنه أيضًا الأكثر تكلفة في التخزين والأبطأ في الإنشاء. النسخ الاحتياطي التزايدييلتقطفقط البيانات التي تغيرت منذ آخر نسخة احتياطية من أي نوع. إنه سريع الإنشاء وصغير الحجم في التخزين، لكن الاستعادة تتطلب إعادة تشغيل السلسلة الكاملة: آخر نسخة احتياطية كاملة بالإضافة إلى كل عملية تزايدية لاحقة. النسخ الاحتياطي التفاضلييلتقطكل ما تغير منذ آخر نسخة احتياطية كاملة. إنها تحتل أرضية متوسطة - أكبر من التزايدية ولكن من الأسهل استعادتها لأنك تحتاج فقط إلى آخر كامل بالإضافة إلى أحدث فرق. أخيرًا، الأرشفة المستمرة لـ(أرشفة WAL في PostgreSQL، وتدفق السجل الثنائي في MySQL) تلتقط كل معاملة فردية فور حدوثها، مما يتيح الاسترداد في أي لحظة بين النسخ الاحتياطية.

نظرة عامة على إستراتيجية النسخ الاحتياطي:الكامل مقابل التزايدي مقابل التفاضلي مقابل المستمراليوم 0اليوم الأولاليوم الثانياليوم الثالثاليوم الرابعاليوم الخامسكاملإنكر.الفرق.وول/Binlogكامل (100%)كامل (100%)+5%+3%+4%+2%+5%+8%+12%+14%استمرار WAL / تدفق السجل الثنائي (كل معاملة)هدف استردادالنسخ الاحتياطي الكاملالتزايديالتفاضليةWAL/Binlog Streamنقطة الاسترداد

الإستراتيجية المثالية لمعظم أنظمة الإنتاج هي الجمع بين: النسخ الاحتياطي الكامل الأسبوعي، والزيادات اليومية أو التفاضلية، والأرشفة المستمرة لـ WAL/binlog. يمنحك هذا استردادًا سريعًا من النسخ الاحتياطية الكاملة الحديثة والقدرة على الاسترداد في أي وقت عندما تحتاج إليه.

MySQL طرق النسخ الاحتياطي

يوفر

MySQL العديد من أدوات النسخ الاحتياطي، كل منها يناسب أحجام قواعد البيانات المختلفة ومتطلبات الاسترداد. يعتمد الاختيار الصحيح على حجم بياناتك ونافذة النسخ الاحتياطي المقبولة وأهداف RTO/RPO.

mysqldump — النسخ الاحتياطي المنطقي العالمي

ينتجmysqldumpعبارات SQL التي تعيد إنشاء المخطط والبيانات. إنه يعمل على كل إصدار ومحرك تخزين MySQL، مما يجعله البديل العالمي. ومع ذلك، فإنه يقوم بتأمين الجداول أثناء التفريغ (ما لم يتم استخدام--single-transactionمع InnoDB)، وتنخفض سرعة الاستعادة بشكل كبير لقواعد البيانات التي تتجاوز 50-100 جيجابايت لأنها تعيد تشغيل عبارات INSERT الفردية.

# Full logical backup with consistent snapshot for InnoDB
mysqldump --single-transaction --routines --triggers --events \
  --set-gtid-purged=ON --all-databases \
  | gzip > /backups/mysql-full-$(date +%Y%m%d-%H%M%S).sql.gz

# Single database backup with compression
mysqldump --single-transaction --routines --triggers \
  --databases production_db \
  | pigz -p4 > /backups/production_db-$(date +%Y%m%d).sql.gz

# Schema-only backup for migration planning
mysqldump --no-data --routines --triggers --events \
  --all-databases > /backups/schema-only-$(date +%Y%m%d).sql

mysqlpump — النسخ الاحتياطي المنطقي الموازي

تم تحسين

mysqlpumpعلىmysqldumpمن خلال تفريغ الجدول المتوازي والضغط المدمج. يمكن أن يقلل بشكل كبير من وقت النسخ الاحتياطي لقواعد البيانات التي تحتوي على العديد من الجداول المستقلة.

# Parallel logical backup with 4 threads and zstd compression
mysqlpump --default-parallelism=4 --compress-output=ZSTD \
  --include-databases=production_db,analytics_db \
  --set-gtid-purged=ON \
  > /backups/mysql-pump-$(date +%Y%m%d).sql.zst

Percona XtraBackup — النسخ الاحتياطي الفعلي لـ InnoDB

بالنسبة لقواعد البيانات التي يزيد حجمها عن 50 جيجابايت، تصبح عمليات النسخ الاحتياطي المنطقي غير عملية - حيث تنمو نافذة النسخ الاحتياطي ووقت الاستعادة بشكل خطي مع حجم البيانات. يأخذ Percona XtraBackup نسخًا على المستوى الفعلي من ملفات بيانات InnoDB دون قفل قاعدة البيانات، مما يجعله مناسبًا لعمليات النشر متعددة التيرابايت.

# Full physical backup with streaming to compressed archive
xtrabackup --backup --target-dir=/backups/full-$(date +%Y%m%d) \
  --user=backup_user --password=secure_pass \
  --parallel=4 --compress --compress-threads=4

# Incremental backup based on last full
xtrabackup --backup --target-dir=/backups/incr-$(date +%Y%m%d) \
  --incremental-basedir=/backups/full-20260412 \
  --user=backup_user --password=secure_pass \
  --parallel=4

# Stream full backup directly to S3 via xbstream
xtrabackup --backup --stream=xbstream --compress \
  --user=backup_user --password=secure_pass | \
  aws s3 cp - s3://db-backups/mysql/full-$(date +%Y%m%d).xbstream

# Prepare for restore (apply redo log)
xtrabackup --prepare --target-dir=/backups/full-20260412

# Prepare incremental on top of full
xtrabackup --prepare --apply-log-only --target-dir=/backups/full-20260412
xtrabackup --prepare --target-dir=/backups/full-20260412 \
  --incremental-dir=/backups/incr-20260412

# Restore
systemctl stop mysqld
xtrabackup --copy-back --target-dir=/backups/full-20260412
chown -R mysql:mysql /var/lib/mysql
systemctl start mysqld

MySQL السجل الثنائي — استرداد النقطة الزمنية

تسجل السجلات الثنائية

MySQL كل بيان تعديل البيانات أو تغيير الصف. عند دمجها مع نسخة احتياطية كاملة أو فعلية، فإنها تتيح إمكانية الاسترداد في وقت محدد في أي لحظة بعد أخذ النسخة الاحتياطية.

# Enable binary logging in my.cnf
[mysqld]
server-id = 1
log-bin = /var/log/mysql/mysql-bin
binlog_format = ROW
binlog_expire_logs_seconds = 604800   # 7 days
sync_binlog = 1
gtid_mode = ON
enforce_gtid_consistency = ON

# Flush and archive binary logs
mysqladmin flush-logs
mysqlbinlog --read-from-remote-server --host=db-primary \
  --raw --stop-never --result-file=/backup/binlogs/ \
  mysql-bin.000042

# Point-in-time recovery: replay binlog up to specific timestamp
mysqlbinlog --stop-datetime="2026-04-12 14:30:00" \
  /backup/binlogs/mysql-bin.000042 \
  /backup/binlogs/mysql-bin.000043 | mysql -u root

PostgreSQL طرق النسخ الاحتياطي

يمكن القول إن النظام البيئي للنسخ الاحتياطي لـ

PostgreSQL أكثر ثراءً من نظام MySQL، مع أدوات الطرف الأول ومجموعة ناضجة من حلول المجتمع المصممة خصيصًا لبيئات الإنتاج واسعة النطاق.

pg_dump وpg_dumpall — النسخ الاحتياطية المنطقية

مثلmysqldump، يقومpg_dumpبإنشاء نسخ احتياطية منطقية. يعد التنسيق المخصص (-Fc) هو التنسيق الافتراضي الموصى به لأنه يدعم الاستعادة المتوازية واستعادة الجدول الانتقائي والضغط المضمن.

# Custom format with parallel dump (4 worker jobs)
pg_dump -Fc -j4 -f /backups/production-$(date +%Y%m%d).dump production_db

# Directory format for maximum parallelism on large databases
pg_dump -Fd -j8 -f /backups/production-$(date +%Y%m%d)/ production_db

# All databases including globals (roles, tablespaces)
pg_dumpall > /backups/pg-all-$(date +%Y%m%d).sql

# Parallel restore from custom format
pg_restore -j4 -d production_db_restored /backups/production-20260412.dump

# Selective restore: single table
pg_restore -j4 -d production_db -t orders /backups/production-20260412.dump

pg_basebackup — مؤسسة النسخ الاحتياطي الفعلي

يأخذpg_basebackupنسخة فعلية من دليل بيانات PostgreSQL بأكمله. إنه الأساس لكل من الاسترداد المستقل وإعداد النسخ المتماثل المتدفق. ومن خلال دمجه مع أرشفة WAL، فإنه يتيح إمكانية الاسترداد في الوقت المناسب.

# Physical backup with WAL files included
pg_basebackup -D /backups/base-$(date +%Y%m%d) \
  -Ft -z -Xs -P -c fast \
  -U replication_user -h db-primary

# Stream backup directly to a tar archive with checksums
pg_basebackup -D - -Ft -Xs -c fast \
  -U replication_user -h db-primary | \
  gzip > /backups/pg-base-$(date +%Y%m%d).tar.gz

pgBackRest — إدارة النسخ الاحتياطي على مستوى المؤسسات

pgBackRest هو المعيار الذهبي لإدارة النسخ الاحتياطي لـ PostgreSQL. وهو يدعم النسخ الاحتياطي الكامل والتزايدي والتفاضلي، والنسخ الاحتياطي والاستعادة المتوازيين، والتشفير، والأهداف متعددة المستودعات (القرص المحلي، S3، GCS، Azure Blob)، وأرشفة WAL الآلية - كل ذلك من خلال تكوين واحد متماسك.

# /etc/pgbackrest/pgbackrest.conf
[global]
repo1-type=s3
repo1-s3-bucket=pg-backups-production
repo1-s3-endpoint=s3.eu-west-1.amazonaws.com
repo1-s3-region=eu-west-1
repo1-s3-key=AKIAIOSFODNN7EXAMPLE
repo1-s3-key-secret=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
repo1-path=/pgbackrest
repo1-retention-full=4
repo1-retention-diff=14
repo1-cipher-type=aes-256-cbc
repo1-cipher-pass=a_very_secure_encryption_passphrase

# Second repository for geographic redundancy
repo2-type=azure
repo2-azure-container=pg-backups-dr
repo2-azure-account=prodbackupstorage
repo2-azure-key=base64encodedkeyhere
repo2-path=/pgbackrest
repo2-retention-full=2

process-max=4
compress-type=zst
compress-level=6
log-level-console=info
log-level-file=detail
start-fast=y

[production]
pg1-path=/var/lib/postgresql/16/main
pg1-port=5432

# PostgreSQL WAL archive configuration (postgresql.conf)
# archive_mode = on
# archive_command = 'pgbackrest --stanza=production archive-push %p'

# Create the stanza
pgbackrest --stanza=production stanza-create

# Verify the stanza configuration
pgbackrest --stanza=production check

# Full backup
pgbackrest --stanza=production --type=full backup

# Differential backup
pgbackrest --stanza=production --type=diff backup

# Incremental backup
pgbackrest --stanza=production --type=incr backup

# List backups
pgbackrest --stanza=production info

WAL-G - أرشفة WAL خفيفة الوزن للتخزين السحابي

يعد

WAL-G بديلاً أبسط لـ pgBackRest الذي يركز على تدفق مقاطع WAL والنسخ الاحتياطية الأساسية لتخزين الكائنات السحابية. إنه شائع في البيئات المعبأة في حاويات حيث تريد ثنائيًا واحدًا بأقل قدر من التكوين.

# Environment variables for WAL-G with S3
export WALG_S3_PREFIX=s3://pg-wal-archive/production
export AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE
export AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
export AWS_REGION=eu-west-1
export WALG_COMPRESSION_METHOD=lz4
export PGHOST=/var/run/postgresql

# Configure WAL archiving in postgresql.conf
# archive_mode = on
# archive_command = 'wal-g wal-push %p'
# restore_command = 'wal-g wal-fetch %f %p'

# Take a base backup
wal-g backup-push /var/lib/postgresql/16/main

# List backups
wal-g backup-list

# Restore from latest backup
wal-g backup-fetch /var/lib/postgresql/16/main LATEST

# Delete old backups (retain last 4)
wal-g delete retain FULL 4 --confirm

Barman — خادم النسخ الاحتياطي المركزي

تم تصميم

Barman (مدير النسخ الاحتياطي والاسترداد) للبيئات التي يقوم فيها خادم نسخ احتياطي مخصص بإدارة النسخ الاحتياطية لمثيلات PostgreSQL المتعددة. وهو يدعم كلاً من بروتوكولات rsync/SSH ونسخ النسخ المتدفق لنقل النسخ الاحتياطي.

# /etc/barman.d/production.conf
[production]
description = "Production PostgreSQL 16"
ssh_command = ssh postgres@db-primary
conninfo = host=db-primary user=barman dbname=postgres
streaming_conninfo = host=db-primary user=streaming_barman
backup_method = postgres
streaming_archiver = on
slot_name = barman
retention_policy = RECOVERY WINDOW OF 14 DAYS

# Create replication slot and start streaming
barman receive-wal --create-slot production
barman switch-wal --force --archive production

# Take a backup
barman backup production

# List backups
barman list-backup production

# Restore to point in time
barman recover --target-time "2026-04-12 14:30:00" \
  production 20260412T120000 /var/lib/postgresql/16/main

استعادة النقاط في الوقت المناسب (PITR)

يعد استرداد

في الوقت المناسب أهم قدرة في مجموعة أدوات النسخ الاحتياطي لديك. فهو يسمح لك باستعادة قاعدة البيانات إلى الحالة الدقيقة التي كانت عليها في أي لحظة محددة - ليس فقط عند أخذ النسخ الاحتياطية، ولكن في أي ثانية بين النسخ الاحتياطية. يعد هذا أمرًا بالغ الأهمية للتعافي من الحذف غير المقصود للبيانات، وأخطاء التطبيق التي تفسد البيانات، والحوادث الأمنية التي تحتاج فيها إلى تحديد اللحظة الدقيقة للاختراق.

استرداد النقطة الزمنية (PITR) الجدول الزمني00:00صن06:0012:0018:0000:00الإثنينالنسخ الاحتياطي الكاملpg_basebackup@ 00:00WAL / قطاعات السجل الثنائي (مستمر)✖طاولة إسقاط@ 16:42:31هدف استرداد@ 16:42:301. استعادةبالكامل2. أعد تشغيل WAL لاستهداف3. تم استرداد قاعدة البيانات!PITR = استعادة آخر نسخة احتياطية كاملة + إعادة تشغيل مقاطع WAL/binlog حتى ثانية واحدة قبل الكارثةدقة استرداد: لكل معاملة (PostgreSQL WAL) أو لكل ثانية (MySQL binlog)

PITR لـ PostgreSQL

يعمل

PostgreSQL PITR عن طريق استعادة نسخة احتياطية أساسية وإعادة تشغيل مقاطع WAL حتى الطابع الزمني المستهدف. مع pgBackRest، العملية برمتها عبارة عن أمر واحد.

# Restore to specific point in time with pgBackRest
pgbackrest --stanza=production \
  --type=time --target="2026-04-12 16:42:30" \
  --target-action=promote \
  restore

# Manual PITR using pg_basebackup + WAL archive
# 1. Stop PostgreSQL
systemctl stop postgresql

# 2. Clear the data directory and restore base backup
rm -rf /var/lib/postgresql/16/main/*
tar xzf /backups/pg-base-20260412.tar.gz -C /var/lib/postgresql/16/main/

# 3. Create recovery signal and configure restore
cat > /var/lib/postgresql/16/main/postgresql.auto.conf << 'CONF'
restore_command = 'cp /backup/wal_archive/%f %p'
recovery_target_time = '2026-04-12 16:42:30'
recovery_target_action = 'promote'
CONF
touch /var/lib/postgresql/16/main/recovery.signal

# 4. Start PostgreSQL — it will replay WAL and stop at target
systemctl start postgresql

PITR لـ MySQL

يجمع

MySQL PITR بين استعادة XtraBackup الفعلية وإعادة تشغيل السجل الثنائي.

# 1. Restore the XtraBackup
systemctl stop mysqld
rm -rf /var/lib/mysql/*
xtrabackup --prepare --target-dir=/backups/full-20260412
xtrabackup --copy-back --target-dir=/backups/full-20260412
chown -R mysql:mysql /var/lib/mysql
systemctl start mysqld

# 2. Identify the binlog position from XtraBackup metadata
cat /backups/full-20260412/xtrabackup_binlog_info
# Output: mysql-bin.000042  154  3E11FA47-1111-1111-1111-AAAAAAAAAAAA:1-1234

# 3. Replay binlogs up to target time
mysqlbinlog --start-position=154 \
  --stop-datetime="2026-04-12 16:42:30" \
  /backup/binlogs/mysql-bin.000042 \
  /backup/binlogs/mysql-bin.000043 | mysql -u root

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

يجب أن تأخذ استراتيجيات النسخ الاحتياطي للإنتاج

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

بنية النسخ الاحتياطي متعدد السحابةPostgreSQLالأساسي + النسخ المتماثلةMySQLالأساسي + النسخ المتماثلةطبقة التشفيرAES-256-CBCTLS قيد النقلSSE-S3 / SSE-KMSفي حالة الراحةتشفير من جانب العميلعبر pgBackRest/WAL-GAWS S3الاتحاد الأوروبي الغربي-1 (الابتدائي)دورة حياة: IA → GlacierAzure النقطةأوروبا الغربية (الابتدائية)سياسات الثباتجوجل التخزين السحابيأوروبا الغربية 1 (الابتدائي)الخط القريب → الخط الباردS3 عبر المناطقلنا-شرق-1 (DR)Azure GRSشمال أوروبا (DR)GCS متعدد المناطقالاتحاد الأوروبي متعدد المناطق (DR)مراقبة النسخ الاحتياطي& تنبيهمقاييسPrometheus • لوحات معلومات Grafana • تنبيهات PagerDuty / Slack عند فشل النسخ الاحتياطي أو عتبة العمرالأسهم الصلبة = التدفق الاحتياطيالأسهم المتقطعة = النسخ المتماثل عبر المناطقمربع متقطع = حدود التشفير

تكوين التخزين السحابي مع سياسات دورة الحياة

# AWS S3 lifecycle policy (Terraform)
resource "aws_s3_bucket_lifecycle_configuration" "backup_lifecycle" {
  bucket = aws_s3_bucket.db_backups.id

  rule {
    id     = "backup-tiering"
    status = "Enabled"

    transition {
      days          = 30
      storage_class = "STANDARD_IA"
    }
    transition {
      days          = 90
      storage_class = "GLACIER"
    }
    transition {
      days          = 365
      storage_class = "DEEP_ARCHIVE"
    }
    expiration {
      days = 2555  # 7 years for compliance
    }
  }

  rule {
    id     = "wal-segments"
    status = "Enabled"
    filter {
      prefix = "wal-archive/"
    }
    expiration {
      days = 30
    }
  }
}

# Enable cross-region replication
resource "aws_s3_bucket_replication_configuration" "backup_replication" {
  bucket = aws_s3_bucket.db_backups.id
  role   = aws_iam_role.replication.arn

  rule {
    id     = "cross-region-dr"
    status = "Enabled"
    destination {
      bucket        = aws_s3_bucket.db_backups_dr.arn
      storage_class = "STANDARD_IA"
      encryption_configuration {
        replica_kms_key_id = aws_kms_key.dr_key.arn
      }
    }
    source_selection_criteria {
      sse_kms_encrypted_objects {
        status = "Enabled"
      }
    }
  }
}
# Azure Blob immutability policy (Azure CLI)
az storage container immutability-policy create \
  --account-name prodbackupstorage \
  --container-name pg-backups \
  --period 365 \
  --allow-protected-append-writes true

# GCS lifecycle with nearline transition
gsutil lifecycle set /dev/stdin gs://pg-backups-production << 'JSON'
{
  "rule": [
    {"action": {"type": "SetStorageClass", "storageClass": "NEARLINE"}, "condition": {"age": 30}},
    {"action": {"type": "SetStorageClass", "storageClass": "COLDLINE"}, "condition": {"age": 90}},
    {"action": {"type": "Delete"}, "condition": {"age": 2555}}
  ]
}
JSON

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

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

هدفًا عالي القيمة للمهاجمين. تمنح النسخة الاحتياطية المسروقة غير المشفرة للمهاجم نسخة كاملة من بيانات الإنتاج الخاصة بك دون الحاجة إلى اختراق أنظمة التشغيل الخاصة بك. يجب تشفير كل نسخة احتياطية، سواء أثناء النقل أو أثناء الراحة.

التشفير أثناء النقليعني استخدام TLS لجميع الاتصالات بين خادم قاعدة البيانات ووجهة النسخ الاحتياطي. يتم بث كل من pgBackRest وXtraBackup عبر القنوات المشفرة عند تكوينهما باستخدام TLS. عند الشحن إلى S3 أو Azure Blob أو GCS، تستخدم مجموعات SDK الخاصة بالعميل HTTPS بشكل افتراضي.

التشفير في حالة الراحة يحتويعلى طبقتين. يقوم التشفير من جانب الخادم (SSE) بتشفير البيانات بعد وصولها إلى هدف التخزين - S3 SSE-KMS، أو Azure Storage Service Encryption، أو التشفير الافتراضي GCS. يقوم التشفير من جانب العميل بتشفير البيانات قبل أن تغادر خادم قاعدة البيانات، مما يضمن عدم رؤية موفر السحابة لبيانات النص العادي مطلقًا. يدعم كل من pgBackRest وWAL-G التشفير من جانب العميل محليًا.

# pgBackRest client-side encryption config
repo1-cipher-type=aes-256-cbc
repo1-cipher-pass=long_random_passphrase_stored_in_vault

# WAL-G client-side encryption
export WALG_LIBSODIUM_KEY=$(cat /etc/wal-g/encryption.key)
# Or GPG-based
export WALG_GPG_KEY_ID=backup@example.com

# MySQL XtraBackup with encryption
xtrabackup --backup --encrypt=AES256 \
  --encrypt-key-file=/etc/mysql/backup-encryption.key \
  --target-dir=/backups/full-encrypted-$(date +%Y%m%d)

قم بتخزين مفاتيح التشفير بشكل منفصل عن النسخ الاحتياطية نفسها. يعد مدير الأسرار مثل HashiCorp Vault أو AWS Secrets Manager أو Azure Key Vault هو الأسلوب الموصى به. إذا قمت بتخزين المفتاح إلى جانب النسخة الاحتياطية، فإن المهاجم الذي يمكنه الوصول إلى مخزن النسخ الاحتياطي الخاص بك سيكون لديه كل ما يحتاج إليه.

جدولة النسخ الاحتياطي الآلي

النسخ الاحتياطية اليدوية ليست نسخًا احتياطية - إنها تطلعات. يجب أن تكون جداول النسخ الاحتياطي آلية ومراقبتها والتنبيه عند الفشل.

نظام

Cron للمعادن العارية وأجهزة VMs

# /etc/cron.d/database-backups

# PostgreSQL — pgBackRest
# Full backup every Sunday at 01:00
0 1 * * 0 postgres pgbackrest --stanza=production --type=full backup 2>&1 | logger -t pgbackrest-full

# Differential backup every day at 01:00 (except Sunday)
0 1 * * 1-6 postgres pgbackrest --stanza=production --type=diff backup 2>&1 | logger -t pgbackrest-diff

# MySQL — XtraBackup
# Full backup every Sunday at 02:00
0 2 * * 0 root /usr/local/bin/mysql-backup.sh full 2>&1 | logger -t xtrabackup-full

# Incremental backup every day at 02:00 (except Sunday)
0 2 * * 1-6 root /usr/local/bin/mysql-backup.sh incremental 2>&1 | logger -t xtrabackup-incr

# Backup verification — restore test every Wednesday at 04:00
0 4 * * 3 root /usr/local/bin/verify-backup.sh 2>&1 | logger -t backup-verify

Kubernetes كرونجوبز

في بيئات Kubernetes، يحل CronJobs محل cron النظام. إنها توفر منطق إعادة المحاولة المدمج والتحكم في التزامن والتكامل مع RBAC الخاص بالمجموعة والإدارة السرية.

apiVersion: batch/v1
kind: CronJob
metadata:
  name: pg-backup-full
  namespace: database
spec:
  schedule: "0 1 * * 0"  # Sunday 01:00 UTC
  concurrencyPolicy: Forbid
  successfulJobsHistoryLimit: 4
  failedJobsHistoryLimit: 3
  jobTemplate:
    spec:
      backoffLimit: 2
      activeDeadlineSeconds: 7200  # 2 hour timeout
      template:
        spec:
          serviceAccountName: db-backup
          restartPolicy: OnFailure
          containers:
            - name: pgbackrest
              image: pgbackrest/pgbackrest:2.50
              command:
                - /bin/bash
                - -c
                - |
                  pgbackrest --stanza=production --type=full backup
                  RESULT=$?
                  if [ $RESULT -eq 0 ]; then
                    curl -s -X POST "$SLACK_WEBHOOK" \
                      -d '{"text":"PostgreSQL full backup completed successfully"}'
                  else
                    curl -s -X POST "$SLACK_WEBHOOK" \
                      -d '{"text":"ALERT: PostgreSQL full backup FAILED"}'
                  fi
                  exit $RESULT
              envFrom:
                - secretRef:
                    name: pgbackrest-credentials
                - secretRef:
                    name: slack-webhook
              resources:
                requests:
                  memory: 512Mi
                  cpu: 500m
                limits:
                  memory: 2Gi
                  cpu: "2"
              volumeMounts:
                - name: pgbackrest-config
                  mountPath: /etc/pgbackrest
          volumes:
            - name: pgbackrest-config
              configMap:
                name: pgbackrest-conf
---
apiVersion: batch/v1
kind: CronJob
metadata:
  name: pg-backup-diff
  namespace: database
spec:
  schedule: "0 1 * * 1-6"  # Mon-Sat 01:00 UTC
  concurrencyPolicy: Forbid
  successfulJobsHistoryLimit: 7
  failedJobsHistoryLimit: 3
  jobTemplate:
    spec:
      backoffLimit: 2
      activeDeadlineSeconds: 3600
      template:
        spec:
          serviceAccountName: db-backup
          restartPolicy: OnFailure
          containers:
            - name: pgbackrest
              image: pgbackrest/pgbackrest:2.50
              command:
                - /bin/bash
                - -c
                - |
                  pgbackrest --stanza=production --type=diff backup
              envFrom:
                - secretRef:
                    name: pgbackrest-credentials
              resources:
                requests:
                  memory: 256Mi
                  cpu: 250m
                limits:
                  memory: 1Gi
                  cpu: "1"
              volumeMounts:
                - name: pgbackrest-config
                  mountPath: /etc/pgbackrest
          volumes:
            - name: pgbackrest-config
              configMap:
                name: pgbackrest-conf
---
apiVersion: batch/v1
kind: CronJob
metadata:
  name: mysql-backup-full
  namespace: database
spec:
  schedule: "0 2 * * 0"
  concurrencyPolicy: Forbid
  jobTemplate:
    spec:
      backoffLimit: 2
      activeDeadlineSeconds: 7200
      template:
        spec:
          serviceAccountName: db-backup
          restartPolicy: OnFailure
          containers:
            - name: xtrabackup
              image: percona/percona-xtrabackup:8.0
              command:
                - /bin/bash
                - -c
                - |
                  xtrabackup --backup --stream=xbstream --compress \
                    --user=$MYSQL_BACKUP_USER \
                    --password=$MYSQL_BACKUP_PASS \
                    --host=mysql-primary.database.svc | \
                    aws s3 cp - s3://$S3_BUCKET/mysql/full-$(date +%Y%m%d).xbstream
              envFrom:
                - secretRef:
                    name: mysql-backup-credentials
                - secretRef:
                    name: aws-credentials
              resources:
                requests:
                  memory: 512Mi
                  cpu: 500m
                limits:
                  memory: 2Gi
                  cpu: "2"

Kubernetes- نهج النسخ الاحتياطي الأصلي

يقدم تشغيل قواعد البيانات في Kubernetes بعدًا جديدًا لاستراتيجية النسخ الاحتياطي. بالإضافة إلى النسخ الاحتياطية لقاعدة البيانات على مستوى التطبيق، يتعين عليك مراعاة النسخ الاحتياطي على مستوى المجموعة (إلخ)، ولقطات الحجم المستمرة، والنسخ الاحتياطية التي يديرها المشغل.

Kubernetes خط أنابيب النسخ الاحتياطيمجموعةKubernetes (k3s / RKE2)كرون جوبجدول: 0 1 * * *جراب النسخ الاحتياطيpgBackRest /حاويةXtraBackupPostgreSQL جرابالنسخة المتماثلةStatefulSet 0PVC: بيانات pgMySQL جرابالنسخة المتماثلةStatefulSet 0PVC: بيانات MySQLقرون طويلة CSIلقطاتالكهروضوئية + النسخ المتماثلةحجم لقطة CRDفيليروالنسخ الاحتياطي على مستوى المجموعةإلخ + مساحات الأسماء + PVsتخزين الكائناتS3 / GCS / Azure Blob / MinIOمشفر & إصدارتم تمكين طبقات دورة حياةالنسخ الاحتياطية لـDB + WALفيليروهدفLonghorn S3 هوPrometheus + Grafanaمقاييس مهمة النسخ الاحتياطي + التنبيهاتمعدل النجاح/الفشل في CronJobمسار الاستعادة1. استعادة Velero (الكتلة)2.pgBackRest/XtraBackup (بيانات)3. التراجع عن لقطة Longhornجدولةوكيل النسخ الاحتياطيPostgreSQLMySQLفيليروقرون طويلةتخزين الكائنات

Velero للنسخ الاحتياطي على مستوى المجموعة

يقوم

Velero بعمل نسخة احتياطية من موارد Kubernetes (عمليات النشر والخدمات وخرائط التكوين والأسرار) ووحدات التخزين المستمرة. وهو ليس بديلاً للنسخ الاحتياطية لقاعدة البيانات على مستوى التطبيق - فهو يلتقط لقطة متسقة من التعطل للوحدات الكهروضوئية، والتي قد لا تكون متسقة من حيث المعاملات لقواعد البيانات. استخدم Velero لاستعادة المجموعة والأدوات على مستوى التطبيق (pgBackRest، XtraBackup) لاستعادة قاعدة البيانات.

# Install Velero with S3 backend
velero install \
  --provider aws \
  --bucket velero-backups \
  --secret-file ./credentials-velero \
  --backup-location-config region=eu-west-1 \
  --snapshot-location-config region=eu-west-1 \
  --use-volume-snapshots=true \
  --plugins velero/velero-plugin-for-aws:v1.9.0

# Create a scheduled backup of the database namespace
velero schedule create db-namespace-backup \
  --schedule="0 3 * * *" \
  --include-namespaces database \
  --ttl 720h \
  --storage-location default \
  --volume-snapshot-locations default

# On-demand backup before maintenance
velero backup create pre-maintenance-$(date +%Y%m%d) \
  --include-namespaces database,monitoring \
  --wait

# Restore a namespace from backup
velero restore create --from-backup pre-maintenance-20260412 \
  --include-namespaces database
لقطات

Longhorn على k3s

تستخدم عمليات نشر

k3s عادةً Longhorn كموفر تخزين CSI الخاص بها. يوفر Longhorn لقطات على مستوى الصوت والقدرة على نسخ اللقطات إلى وحدة تخزين الكائنات المتوافقة مع S3. بالنسبة لقواعد البيانات، قم بدمج لقطات Longhorn مع النسخ الاحتياطية على مستوى التطبيق للدفاع بعمق.

# Longhorn recurring snapshot job via CRD
apiVersion: longhorn.io/v1beta2
kind: RecurringJob
metadata:
  name: pg-data-snapshot
  namespace: longhorn-system
spec:
  cron: "0 */4 * * *"  # every 4 hours
  task: snapshot
  retain: 6
  concurrency: 1
  groups:
    - pg-data
  labels:
    app: postgresql
---
# Longhorn recurring backup to S3
apiVersion: longhorn.io/v1beta2
kind: RecurringJob
metadata:
  name: pg-data-s3-backup
  namespace: longhorn-system
spec:
  cron: "0 2 * * *"  # daily at 02:00
  task: backup
  retain: 14
  concurrency: 1
  groups:
    - pg-data
  labels:
    app: postgresql
---
# VolumeSnapshot using Longhorn CSI
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata:
  name: pg-data-snap-$(date +%Y%m%d)
  namespace: database
spec:
  volumeSnapshotClassName: longhorn-snapshot-vsc
  source:
    persistentVolumeClaimName: pg-data-postgresql-0

النسخ الاحتياطية التي يديرها المشغل

يقوم مشغلو قواعد البيانات

مثل CloudNativePG (لـ PostgreSQL) وPercona Operator (لـ MySQL) بدمج إدارة النسخ الاحتياطي مباشرة في دورة حياة قاعدة البيانات. يتعامل المشغل مع الجدولة وأرشفة WAL والاحتفاظ تلقائيًا من خلال الموارد المخصصة.

# CloudNativePG cluster with integrated backup
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: production-pg
  namespace: database
spec:
  instances: 3
  storage:
    size: 100Gi
    storageClass: longhorn
  backup:
    barmanObjectStore:
      destinationPath: s3://pg-backups/cnpg/
      endpointURL: https://s3.eu-west-1.amazonaws.com
      s3Credentials:
        accessKeyId:
          name: aws-creds
          key: ACCESS_KEY_ID
        secretAccessKey:
          name: aws-creds
          key: SECRET_ACCESS_KEY
      wal:
        compression: gzip
        maxParallel: 4
      data:
        compression: gzip
    retentionPolicy: "30d"
---
apiVersion: postgresql.cnpg.io/v1
kind: ScheduledBackup
metadata:
  name: production-pg-weekly
  namespace: database
spec:
  schedule: "0 1 * * 0"
  backupOwnerReference: self
  cluster:
    name: production-pg
استراتيجيات

الخاصة بموفر الخدمة السحابية

AWS — RDS وأورورا

يوفر

AWS RDS لقطات يومية تلقائية مع الاحتفاظ القابل للتكوين (حتى 35 يومًا) والنسخ الاحتياطي المستمر عبر أرشفة سجل المعاملات من أجل الاسترداد في الوقت المناسب. تضيف Aurora خاصية Backtrack، والتي يمكنها إرجاع المجموعة إلى أي نقطة داخل نافذة التراجع دون الحاجة إلى استعادة - فهي ببساطة تعكس الحالة الداخلية لقاعدة البيانات.

# Enable automated backups with maximum retention (Terraform)
resource "aws_db_instance" "production" {
  identifier             = "production-pg"
  engine                 = "postgres"
  engine_version         = "16.2"
  instance_class         = "db.r6g.xlarge"
  allocated_storage      = 500
  backup_retention_period = 35  # maximum
  backup_window          = "03:00-04:00"
  copy_tags_to_snapshot  = true
  deletion_protection    = true
  storage_encrypted      = true
  kms_key_id             = aws_kms_key.rds.arn

  # Enable PITR
  enabled_cloudwatch_logs_exports = ["postgresql", "upgrade"]
}

# Cross-region automated backup replication
resource "aws_db_instance_automated_backups_replication" "dr" {
  source_db_instance_arn = aws_db_instance.production.arn
  kms_key_id             = aws_kms_key.dr_rds.arn
  retention_period       = 14
}

# Aurora Backtrack (MySQL-compatible Aurora only)
resource "aws_rds_cluster" "aurora_production" {
  cluster_identifier      = "aurora-production"
  engine                  = "aurora-mysql"
  engine_version          = "8.0.mysql_aurora.3.05.2"
  backtrack_window        = 86400  # 24 hours of backtrack
  backup_retention_period = 35
  preferred_backup_window = "03:00-04:00"
  storage_encrypted       = true
}

# Manual snapshot with cross-region copy
aws rds create-db-snapshot \
  --db-instance-identifier production-pg \
  --db-snapshot-identifier pre-migration-$(date +%Y%m%d)

aws rds copy-db-snapshot \
  --source-db-snapshot-identifier arn:aws:rds:eu-west-1:123456789:snapshot:pre-migration-20260412 \
  --target-db-snapshot-identifier pre-migration-20260412-dr \
  --source-region eu-west-1 \
  --region us-east-1 \
  --kms-key-id arn:aws:kms:us-east-1:123456789:key/dr-key-id

Azure — خادم مرن

تشتمل قاعدة بيانات

Azure للخادم المرن PostgreSQL وMySQL على نسخ احتياطية تلقائية مع مساحة تخزين زائدة محليًا أو جغرافية زائدة عن الحاجة. يتيح النسخ الاحتياطي الجغرافي المتكرر إمكانية الاستعادة عبر المناطق للتعافي من الكوارث.

# Azure Flexible Server with geo-redundant backup (Terraform)
resource "azurerm_postgresql_flexible_server" "production" {
  name                = "production-pg"
  location            = "westeurope"
  resource_group_name = azurerm_resource_group.db.name
  sku_name            = "GP_Standard_D4s_v3"
  version             = "16"
  storage_mb          = 524288  # 512 GB

  backup_retention_days        = 35
  geo_redundant_backup_enabled = true

  authentication {
    active_directory_auth_enabled = true
    password_auth_enabled         = false
  }
}

# Azure Blob immutability for self-managed backups
resource "azurerm_storage_management_policy" "backup_lifecycle" {
  storage_account_id = azurerm_storage_account.backups.id

  rule {
    name    = "backup-tiering"
    enabled = true
    filters {
      blob_types   = ["blockBlob"]
      prefix_match = ["pg-backups/"]
    }
    actions {
      base_blob {
        tier_to_cool_after_days_since_modification_greater_than    = 30
        tier_to_archive_after_days_since_modification_greater_than = 90
        delete_after_days_since_modification_greater_than          = 2555
      }
    }
  }
}

GCP — السحابة SQL

يوفر

Cloud SQL نسخًا احتياطية آلية واستردادًا فوريًا خارج الصندوق. بالنسبة لقواعد البيانات المُدارة ذاتيًا على GCE أو GKE، توفر GCS مع فئات تخزين الخطوط القريبة والخطوط الباردة تخزينًا احتياطيًا فعالاً من حيث التكلفة على المدى الطويل.

# Cloud SQL with automated backups and PITR (Terraform)
resource "google_sql_database_instance" "production" {
  name             = "production-pg"
  database_version = "POSTGRES_16"
  region           = "europe-west1"

  settings {
    tier = "db-custom-4-16384"

    backup_configuration {
      enabled                        = true
      start_time                     = "03:00"
      point_in_time_recovery_enabled = true
      transaction_log_retention_days = 7
      backup_retention_settings {
        retained_backups = 30
        retention_unit   = "COUNT"
      }
    }

    ip_configuration {
      ssl_mode = "ENCRYPTED_ONLY"
    }
  }
}

# Export to GCS for long-term retention
gcloud sql export sql production-pg \
  gs://pg-backups-longterm/export-$(date +%Y%m%d).sql.gz \
  --database=production_db \
  --offload

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

النسخة الاحتياطية التي لم يتم اختبارها من قبل ليست نسخة احتياطية - إنها أمل. يجب أن يتم تشغيل اختبار الاستعادة التلقائي وفقًا لجدول زمني منتظم، ويفضل أن يكون أسبوعيًا، في بيئة معزولة. يجب أن يتحقق الاختبار ليس فقط من اكتمال عملية الاستعادة دون أخطاء، بل أيضًا من أن البيانات المستعادة متسقة ويمكن للتطبيق الاتصال بها والاستعلام عنها.

#!/bin/bash
# verify-backup.sh — Automated backup verification script
set -euo pipefail

RESTORE_DIR="/tmp/backup-verify-$(date +%Y%m%d-%H%M%S)"
LOG_FILE="/var/log/backup-verify.log"
SLACK_WEBHOOK="${SLACK_WEBHOOK_URL}"
DB_TYPE="${1:-postgresql}"  # postgresql or mysql

log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOG_FILE"; }
alert() {
  log "ALERT: $*"
  curl -s -X POST "$SLACK_WEBHOOK" \
    -H 'Content-Type: application/json' \
    -d "{\"text\":\"BACKUP VERIFY FAILED: $*\"}"
}

cleanup() {
  log "Cleaning up $RESTORE_DIR"
  rm -rf "$RESTORE_DIR"
  if [ "$DB_TYPE" = "postgresql" ]; then
    pg_ctlcluster 16 verify stop 2>/dev/null || true
  else
    mysqladmin -S /tmp/mysql-verify.sock shutdown 2>/dev/null || true
  fi
}
trap cleanup EXIT

mkdir -p "$RESTORE_DIR"

if [ "$DB_TYPE" = "postgresql" ]; then
  log "Starting PostgreSQL backup verification"

  # Restore latest pgBackRest backup to temporary directory
  pgbackrest --stanza=production \
    --pg1-path="$RESTORE_DIR/pgdata" \
    --type=immediate \
    --target-action=promote \
    restore 2>&1 | tee -a "$LOG_FILE"

  if [ ${PIPESTATUS[0]} -ne 0 ]; then
    alert "pgBackRest restore failed"
    exit 1
  fi

  # Start PostgreSQL on a different port
  pg_ctlcluster 16 verify start -- \
    -D "$RESTORE_DIR/pgdata" \
    -o "-p 5433" \
    -o "-c listen_addresses=127.0.0.1"

  sleep 5

  # Verify data integrity
  TABLES=$(psql -p 5433 -d production_db -t -c \
    "SELECT count(*) FROM information_schema.tables WHERE table_schema='public';")
  log "Verified $TABLES tables exist"

  ROW_CHECK=$(psql -p 5433 -d production_db -t -c \
    "SELECT count(*) FROM orders WHERE created_at > now() - interval '7 days';")
  log "Recent orders count: $ROW_CHECK"

  if [ "$ROW_CHECK" -lt 1 ]; then
    alert "PostgreSQL restore has no recent data — possible stale backup"
    exit 1
  fi

  # Run pg_amcheck for corruption detection (PostgreSQL 14+)
  pg_amcheck -p 5433 -d production_db --heapallindexed 2>&1 | tee -a "$LOG_FILE"

  log "PostgreSQL backup verification PASSED"

else
  log "Starting MySQL backup verification"

  # Prepare and restore latest XtraBackup
  LATEST_FULL=$(ls -td /backups/full-* | head -1)
  cp -r "$LATEST_FULL" "$RESTORE_DIR/mysql-data"
  xtrabackup --prepare --target-dir="$RESTORE_DIR/mysql-data"

  # Start MySQL on a different socket and port
  mysqld --datadir="$RESTORE_DIR/mysql-data" \
    --socket=/tmp/mysql-verify.sock \
    --port=3307 \
    --skip-networking=0 \
    --bind-address=127.0.0.1 &

  sleep 10

  # Verify data
  TABLES=$(mysql -S /tmp/mysql-verify.sock -e \
    "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema='production_db';" -sN)
  log "Verified $TABLES tables exist"

  mysqlcheck -S /tmp/mysql-verify.sock --all-databases --check 2>&1 | tee -a "$LOG_FILE"

  log "MySQL backup verification PASSED"
fi

curl -s -X POST "$SLACK_WEBHOOK" \
  -H 'Content-Type: application/json' \
  -d "{\"text\":\"Backup verification PASSED for $DB_TYPE at $(date)\"}"

log "Verification complete"

تخطيط التعافي من الكوارث: RTO وRPO

يجب تصميم كل إستراتيجية نسخ احتياطي حول مقياسين: هدف وقت الاسترداد (RTO)- المدة التي يمكنك تحملها للتوقف - وهدف نقطة الاسترداد (RPO)- مقدار البيانات التي يمكنك تحمل خسارتها. تدفع هذه الأرقام كل قرار بشأن تكرار النسخ الاحتياطي وأسلوبه وبنيته.

تطبيقتحليلات
السيناريوRTORPOاستراتيجية
الخروج من التجارة الإلكترونية< 5 دقائق0 (فقدان البيانات صفر)النسخ المتماثل المتزامن + أرشفة WAL المستمرة + تجاوز الفشل في وضع الاستعداد
SaaS< 30 دقيقة< دقيقة واحدة مننسخ البث + الأرشفة المستمرة WAL-G + تجاوز الفشل الآلي
الأدوات الداخلية< 4 ساعات< ساعة واحدةتفاضل يومي + تزايدي بالساعة + أرشفة WAL
/ مستودع البيانات< 24 ساعة< 24 ساعةنسخ احتياطي يومي كامل للتخزين السحابي
Dev / التدريج< 48 ساعة< أسبوع واحدنسخ احتياطي أسبوعي كامل

للحصول على صفر RPO، تحتاج إلى النسخ المتماثل المتزامن في وضع الاستعداد واحد على الأقل. وهذا يضيف زمن الوصول إلى كل معاملة كتابة ولكنه يضمن عدم فقدان أي معاملة ملتزم بها. تقبل معظم أنظمة الإنتاج ما يقارب الصفر من RPO (ثواني الخسارة المحتملة) باستخدام النسخ المتماثل المتدفق غير المتزامن مع أرشفة WAL/binlog المستمرة، مما يتجنب عقوبة زمن استجابة الكتابة.

قالب دليل التشغيل للتعافي من الكوارث

# DR Runbook: Database Recovery

## Severity Levels
- P1: Complete data loss / corruption — all hands, CEO notified
- P2: Partial data loss / single region down — on-call team + escalation
- P3: Replica failure / backup failure — on-call investigation

## Recovery Procedures

### Scenario A: Primary DB failure, replicas healthy
1. Promote replica to primary (automated via Patroni / orchestrator)
2. Verify application connectivity
3. Re-establish replication from new primary
4. Investigate root cause

### Scenario B: Complete cluster failure, backups intact
1. Provision new database infrastructure
2. Restore latest full backup
3. Apply WAL/binlog to reach latest consistent point
4. Verify data integrity with checksums
5. Update DNS / connection strings
6. Resume application traffic
7. Re-establish backup schedule immediately

### Scenario C: Data corruption (bad migration / SQL injection)
1. Identify exact timestamp of corruption
2. Restore to point-in-time just before corruption
3. Export affected tables from restored copy
4. Merge clean data into production
5. OR: full PITR restore if corruption is widespread

## Contacts
- DBA on-call: [PagerDuty rotation]
- Infrastructure: [PagerDuty rotation]
- VP Engineering: [phone number]

## Validation Checklist
- [ ] Application health checks pass
- [ ] Row counts match expected ranges
- [ ] Recent transactions are present
- [ ] Replication re-established
- [ ] Backup schedule resumed
- [ ] Post-incident review scheduled

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

أنظمة النسخ الاحتياطي

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

# Prometheus alerting rules for backup monitoring
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  name: backup-alerts
  namespace: monitoring
spec:
  groups:
    - name: database-backups
      rules:
        - alert: BackupTooOld
          expr: |
            (time() - backup_last_successful_timestamp_seconds) > 90000
          for: 10m
          labels:
            severity: critical
          annotations:
            summary: "Database backup is older than 25 hours"
            description: "Last successful backup for {{ $labels.database }} was {{ $value | humanizeDuration }} ago"

        - alert: BackupJobFailed
          expr: |
            kube_job_status_failed{job_name=~".*backup.*"} > 0
          for: 5m
          labels:
            severity: critical
          annotations:
            summary: "Backup CronJob failed: {{ $labels.job_name }}"

        - alert: WALArchivingLagging
          expr: |
            pg_stat_archiver_failed_count > 0
          for: 5m
          labels:
            severity: warning
          annotations:
            summary: "PostgreSQL WAL archiving has failures"

        - alert: BackupStorageQuotaNearing
          expr: |
            (backup_storage_used_bytes / backup_storage_quota_bytes) > 0.85
          for: 30m
          labels:
            severity: warning
          annotations:
            summary: "Backup storage at {{ $value | humanizePercentage }} capacity"

        - alert: BinlogSpaceCritical
          expr: |
            mysql_binlog_size_bytes > 53687091200
          for: 10m
          labels:
            severity: warning
          annotations:
            summary: "MySQL binlog space exceeds 50GB — check archiving"
# Custom Prometheus exporter for pgBackRest metrics
#!/usr/bin/env python3
"""pgBackRest Prometheus exporter — exposes backup age and size metrics."""
import json
import subprocess
import time
from prometheus_client import start_http_server, Gauge

BACKUP_AGE = Gauge('pgbackrest_last_backup_age_seconds', 'Seconds since last backup', ['stanza', 'type'])
BACKUP_SIZE = Gauge('pgbackrest_last_backup_size_bytes', 'Size of last backup', ['stanza', 'type'])
BACKUP_REPO_SIZE = Gauge('pgbackrest_repo_size_bytes', 'Total repository size', ['stanza'])

def collect():
    result = subprocess.run(
        ['pgbackrest', '--output=json', 'info'],
        capture_output=True, text=True
    )
    info = json.loads(result.stdout)
    for stanza_info in info:
        stanza = stanza_info['name']
        for backup in stanza_info.get('backup', []):
            backup_type = backup['type']
            stop_time = backup['timestamp']['stop']
            age = time.time() - stop_time
            BACKUP_AGE.labels(stanza=stanza, type=backup_type).set(age)
            size = backup['info']['size']
            BACKUP_SIZE.labels(stanza=stanza, type=backup_type).set(size)

if __name__ == '__main__':
    start_http_server(9854)
    while True:
        collect()
        time.sleep(300)

الأخطاء الشائعة والأنماط المضادة

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

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

2. لا يتم اختبار الاستعادة أبدًا.النسخة الاحتياطية التي لا يمكن استعادتها ليست نسخة احتياطية. قم بجدولة اختبارات الاستعادة التلقائية أسبوعيًا واطلب من المهندسين إجراء تدريبات الاستعادة اليدوية كل ثلاثة أشهر.

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

4. عدم مراقبة مهام النسخ الاحتياطي. تفشل وظائفCron بصمت. تم تعليق Kubernetes CronJobs. تنتهي صلاحية بيانات اعتماد S3. يجب أن تقوم كل مهمة نسخ احتياطي بإبلاغ نظام المراقبة بالنجاح أو الفشل، والتنبيه إذا كانت أحدث نسخة احتياطية ناجحة أقدم من RPO الخاص بك.

5. تخزين مفاتيح التشفير بجانب النسخ الاحتياطية.إذا تمكن أحد المهاجمين من الوصول إلى مخزن النسخ الاحتياطي الخاص بك، فلا ينبغي أن يكون لديه أيضًا مفتاح فك التشفير. قم بتخزين المفاتيح في مدير أسرار مخصص.

6. لا توجد سياسة للاحتفاظ.بدون سياسات دورة الحياة، ينمو تخزين النسخ الاحتياطي بلا حدود. تحديد فترات احتفاظ واضحة: 7 أيام لشرائح WAL، و30 يومًا للنسخ الاحتياطي اليومي، و12 شهرًا للنسخ الاحتياطية الشهرية، وحذفها تلقائيًا.

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

8. استخدامmysqldumpلقواعد البيانات الكبيرة بدون--single-transaction.بدون هذه العلامة، يقومmysqldumpبتأمين الجداول وحظر الكتابة طوال مدة التفريغ. بالنسبة لقواعد البيانات الكبيرة، قد يعني هذا دقائق أو ساعات من التوقف.

9. نسيان عمل نسخة احتياطية لتكوين قاعدة البيانات.استعادة البيانات ليست سوى نصف المعركة. إذا فقدتpostgresql.confوpg_hba.confوmy.cnfوإعدادات النسخ المتماثل ومنح المستخدم، فلن تتمكن من إعادة قاعدة البيانات إلى حالة قابلة للاستخدام. قم بتضمين ملفات التكوين في عملية النسخ الاحتياطي.

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

تحسين تكلفة

لتخزين النسخ الاحتياطية

يمكن أن تنمو تكاليف تخزين النسخ الاحتياطية

بسرعة، خاصة مع النسخ الاحتياطية الكاملة المتكررة لقواعد البيانات الكبيرة. تعمل هذه الاستراتيجيات على إبقاء التكاليف تحت السيطرة دون المساس بإمكانية الاسترداد.

استخدم النسخ الاحتياطية التزايدية/التفاضلية.تستخدم الفروق الأسبوعية الكاملة بالإضافة إلى الفروق اليومية جزءًا صغيرًا من مساحة التخزين مقارنة بالنسخ الاحتياطية الكاملة اليومية. تعني إمكانية استعادة دلتا الخاصة بـ pgBackRest أن استعادة النسخ الاحتياطية المتزايدة بنفس سرعة النسخ الاحتياطية الكاملة تقريبًا.

تمكين الضغط.توفر خوارزميات الضغط الحديثة مثل zstd نسب ضغط ممتازة (5:1 إلى 10:1 لبيانات قاعدة البيانات النموذجية) مع الحد الأدنى من حمل CPU. يدعم كل من pgBackRest وXtraBackup zstd محليًا.

تنفيذ طبقات التخزين.انقل النسخ الاحتياطية إلى طبقات تخزين أرخص تدريجيًا مع تقدم العمر. يمكن لسياسات دورة الحياة الموضحة سابقًا (S3 Standard → IA → Glacier، GCS Standard → Nearline → Coldline) تقليل تكاليف التخزين طويل المدى بنسبة 70-90%.

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

نوافذ الاحتفاظ بالحجم الصحيح.تتخلف العديد من الفرق عن الاحتفاظ بالنسخ الاحتياطية إلى الأبد بعيدًا عن الحذر. قم بتحليل أنماط الاسترداد الفعلية ومتطلبات الامتثال، ثم قم بتعيين الاحتفاظ المطابق. يمكن لمتطلبات الاحتفاظ لمدة 7 سنوات استخدام تخزين أرشيف عميق بأقل من 1 دولار أمريكي لكل تيرابايت شهريًا لدى معظم موفري الخدمات السحابية.

# Cost comparison: Full vs Incremental backup storage
# Assuming 500 GB database, 5% daily change rate, 30-day retention

# Strategy A: Daily full backups
# 500 GB × 30 days = 15,000 GB = 15 TB
# S3 Standard: 15 TB × $0.023/GB = $345/month

# Strategy B: Weekly full + daily incremental
# 4 full × 500 GB = 2,000 GB
# 26 incremental × 25 GB = 650 GB
# Total: 2,650 GB ≈ 2.6 TB
# S3 Standard: 2.6 TB × $0.023/GB = $59.80/month

# Strategy C: Strategy B + lifecycle tiering
# Current week: 525 GB Standard = $12.08
# Weeks 2-4: 2,125 GB Standard-IA = $26.56
# Total: $38.64/month

# Savings: Strategy C is 89% cheaper than Strategy A

تجميع كل شيء معًا: بنية نسخ احتياطي كاملة

فيما يلي بنية النسخ الاحتياطي الموصى بها لبيئة الإنتاج التي تشغل كلاً من MySQL وPostgreSQL، والتي تم نشرها على Kubernetes مع التعافي من الكوارث على السحابة المتعددة.

لـ PostgreSQL:

  • pgBackRest كأداة النسخ الاحتياطي الأساسية مع مستودعين (S3 + Azure Blob)
  • أرشفة WAL المستمرة لكلا المستودعين
  • النسخ الاحتياطي الكامل الأسبوعي + التفاضلي اليومي (عبر K8s CronJob) لقطات حجم
  • Longhorn كل 4 ساعات للرجوع السريع إلى الحالة السابقة
  • التحقق من الاستعادة التلقائية كل أربعاء
  • مراقبة
  • Prometheus مع تنبيهات بشأن عمر النسخ الاحتياطي والفشل والتخزين

لـ MySQL:

  • Percona XtraBackup للنسخ الاحتياطية الفعلية المتدفقة إلى S3
  • شحن السجل الثنائي المستمر إلى وحدة تخزين منفصلة
  • أسبوعي كامل + يومي تزايدي (عبر K8s CronJob)
  • mysqldumpاليومي للمخططات الهامة للنسخ الاحتياطي المنطقي المحمول
  • لقطات حجم
  • Longhorn كل 4 ساعات
  • التحقق من الاستعادة التلقائية كل يوم خميس

لمجموعة Kubernetes:

  • Velero النسخ الاحتياطي اليومي لمساحات أسماء قاعدة البيانات مع اللقطات الكهروضوئية
  • لقطات
  • RKE2/k3s وما إلى ذلك كل 6 ساعات للتخزين خارج المجموعة
  • مستودع
  • GitOps كمصدر الحقيقة لجميع بيانات

للتعافي من الكوارث:

    النسخ المتماثل عبر المنطقة
  • S3 إلى منطقة DR
  • Azure GRS للنسخ الاحتياطية الجغرافية الزائدة
  • تمرين DR الشهري
  • : إعادة بناء المجموعة الكاملة من النسخ الاحتياطية في منطقة DR
  • دليل التشغيل الموثق مع شجرة القرار لكل سيناريو فشل
استنتاج

تعد النسخ الاحتياطية لقاعدة البيانات

خط الدفاع الأخير بين عملك وفقدان البيانات الكارثي. تمثل الاستراتيجيات الموضحة في هذه المقالة - النسخ الاحتياطية المادية والمنطقية، والأرشفة المستمرة لـ WAL وbinlog، والتخزين السحابي المتعدد مع سياسات دورة الحياة، والتشفير في كل طبقة، والجدولة التلقائية عبر Kubernetes CronJobs، والتحقق المنهجي من الاستعادة - الحالة الفنية الحالية لبيئات الإنتاج MySQL وPostgreSQL.

أهم ما يمكن تعلمه هو:استراتيجية النسخ الاحتياطي جيدة مثل اختبار الاستعادة الناجح الأخير. كل أداة ونص برمجي ونمط بنية موجود في هذه المقالة يخدم غرضًا واحدًا - وهو ضمان أنه عندما يحدث الأسوأ، يمكنك استرداد بياناتك، والوفاء بالتزامات RTO وRPO، والحفاظ على استمرارية أعمالك. قم ببناء نظام النسخ الاحتياطي الخاص بك، وقم بتشغيله تلقائيًا، وراقبه، واختبره، ثم اختبره مرة أخرى. سوف تشكرك نفسك في المستقبل.