45 Backup und Restore: Die letzte Verteidigungslinie

Backups sind Versicherung gegen das Unvorstellbare. Hardware-Failures, Software-Bugs, Human-Errors, Ransomware-Attacks – all dies kann Production-Daten vernichten. Ein versehentlicher db.collection.drop() auf der falschen Database. Ein Bug, der Millionen Dokumente korrupt. Ein Datacenter-Brand. Diese Szenarien sind selten, aber nicht unmöglich. Wenn sie passieren, ist ein funktionierendes Backup der Unterschied zwischen “Daten restored in 2 Stunden” und “Business bankrupt”.

Aber Backups sind nutzlos wenn sie nicht getestet sind. Die berüchtigtste Backup-Geschichte in Tech: GitLab’s 2017 Incident, wo ein Engineer versehentlich eine Production-Database dropped. Backups existierten – aber fünf verschiedene Backup-Systeme hatten alle Failures, und nur 6 Stunden Data konnten recovered werden aus 18 Stunden. Der Post-Mortem: “Backups wurden nie getestet.” Dies ist die kritische Lesson: Backups existieren ist nicht genug – sie müssen regelmäßig tested und validated werden.

Dieses Kapitel behandelt Backup-Strategien systematisch – von simple mongodump für kleine Databases über Filesystem-Snapshots für large-scale bis zu Point-in-Time-Recovery für Enterprise-Requirements. Der Fokus ist auf Production-Ready-Solutions mit emphasis auf Testing und Disaster-Recovery-Planning.

45.1 Die Backup-Grundfrage: RTO und RPO

Bevor man eine Backup-Strategy wählt, muss man zwei Metriken definieren:

Recovery Time Objective (RTO): Wie schnell muss die Database restored werden? 1 Stunde? 24 Stunden? Eine Woche?

Recovery Point Objective (RPO): Wie viel Data-Loss ist akzeptabel? Null Data-Loss? 1 Stunde? 24 Stunden?

Diese definieren die Backup-Frequency und -Method:

RPO Backup-Frequency Method
24 hours Daily mongodump, Filesystem-Snapshot
1 hour Hourly Continuous-Backup (Oplog), Snapshots
< 1 minute Continuous Replica-Sets mit delayed-members, Point-in-Time
Zero (keine Data-Loss) Real-Time Geographically-distributed Replica-Sets

Für ein E-Commerce-System während Black-Friday könnte RPO = 1 Minute sein (jede Minute Data-Loss = tausende verlorene Orders). Für ein Internal-Tool könnte RPO = 24 Stunden akzeptabel sein.

RTO bestimmt die Restore-Speed. Wenn RTO = 1 Stunde, braucht man fast-restores – etwa Filesystem-Snapshots oder Hot-Standby-Replicas. Wenn RTO = 24 Stunden, kann man langsamer aber günstigere Methods nutzen – etwa Tape-Backups oder Cold-Storage.

45.2 mongodump und mongorestore: Die Basics

mongodump ist MongoDB’s built-in Backup-Tool. Es exportiert Database-Content zu BSON-Files – ein logical Backup, nicht ein Physical-Copy.

# Backup entire database
mongodump --uri="mongodb://user:pass@host:27017/mydb" --out=/backup/mongodb-$(date +%Y%m%d)

# Backup specific collection
mongodump --uri="mongodb://user:pass@host:27017/mydb" --collection=users --out=/backup/users-$(date +%Y%m%d)

# Backup mit Compression
mongodump --uri="mongodb://user:pass@host:27017/mydb" --gzip --out=/backup/mongodb-$(date +%Y%m%d)

Dies created eine Directory-Structure:

/backup/mongodb-20240120/
├── mydb/
│   ├── users.bson
│   ├── users.metadata.json
│   ├── orders.bson
│   ├── orders.metadata.json
│   └── ...

Restore:

# Restore entire database
mongorestore --uri="mongodb://user:pass@host:27017" --drop /backup/mongodb-20240120

# Restore specific collection
mongorestore --uri="mongodb://user:pass@host:27017/mydb" --collection=users /backup/mongodb-20240120/mydb/users.bson

Der --drop-Flag droppt existierende Collections vor Restore – ohne ihn merged mongorestore neue Daten mit existierenden (was meist unerwünscht ist).

mongodump Characteristics:

Pros: - Simple und intuitive - Granular: Kann einzelne Collections backupen - Platform-Independent: BSON-Files funktionieren cross-platform - Compressed: Mit --gzip spart Speicher

Cons: - Langsam bei großen Databases (GB-scale ist OK, TB-scale problematisch) - Nicht atomic: Backup reflektiert nicht einen Single-Point-in-Time wenn Database während Backup modifiziert wird - Kein Built-in-Encryption: Backup-Files sind unencrypted (kann via Filesystem-Encryption gehandelt werden)

Use-Case:

mongodump ist perfekt für: - Small-to-Medium Databases (< 100 GB) - Development/Staging-Environments - Selective-Collection-Backups - Database-Migrations zwischen Environments

Für Large-Scale-Production oder Databases mit < 1-Hour-RPO ist mongodump oft nicht ausreichend.

45.3 Filesystem-Snapshots: Speed und Consistency

Filesystem-Snapshots sind Copy-on-Write-Clones des Database-Directories. Modern Filesystems (LVM, ZFS, XFS, Btrfs) und Cloud-Storage (AWS-EBS, GCP-Persistent-Disks) unterstützen Snapshots – sie sind near-instant, selbst für TB-scale-Databases.

Vorgehen:

# 1. Ensure Journaling ist enabled (Default seit MongoDB 4.0)
# Journaling garantiert Crash-Consistency

# 2. Optional: Flush und lock (nur nötig wenn Journaling disabled)
mongosh --eval "db.fsyncLock()"

# 3. Create Snapshot (AWS EBS example)
aws ec2 create-snapshot --volume-id vol-1234567890abcdef0 --description "MongoDB backup 2024-01-20"

# 4. Unlock (wenn locked)
mongosh --eval "db.fsyncUnlock()"

Der Snapshot ist ein Point-in-Time-Copy. MongoDB muss nicht gestoppt werden – dank Journaling ist der Snapshot crash-consistent (wie nach einem unerwarteten Shutdown – MongoDB kann recovern via Journal-Replay).

Restore from Snapshot:

# 1. Stop MongoDB
sudo systemctl stop mongod

# 2. Create Volume from Snapshot
aws ec2 create-volume --snapshot-id snap-1234567890abcdef0 --availability-zone us-east-1a

# 3. Attach Volume zum Server
aws ec2 attach-volume --volume-id vol-0987654321fedcba0 --instance-id i-1234567890abcdef0 --device /dev/sdf

# 4. Mount Volume
sudo mount /dev/sdf /var/lib/mongodb

# 5. Start MongoDB
sudo systemctl start mongod

MongoDB startet, replayed das Journal (wenn nötig), und ist operational.

Snapshot-Performance:

Snapshots sind orders-of-magnitude schneller als mongodump:

Method 100 GB Database 1 TB Database
mongodump ~30 minutes ~5 hours
Filesystem-Snapshot < 1 minute < 1 minute

Snapshot-Limitations:

  1. Filesystem/Cloud-Dependent: Funktioniert nur auf Systemen mit Snapshot-Support
  2. Full-Volume-Snapshot: Man kann nicht einzelne Collections backupen
  3. Same-Platform-Restore: Snapshots sind meist nicht cross-platform (EBS-Snapshot funktioniert nicht auf GCP)

Use-Case:

Snapshots sind optimal für: - Large Databases (> 100 GB) - Low-RTO-Requirements (< 1 hour) - Cloud-Hosted-MongoDB (AWS, GCP, Azure) - Full-Database-Backups

45.4 Replica-Set-Backups: Zero-Impact on Primary

In Replica-Sets kann man Backups vom Secondary-Node nehmen ohne Primary-Performance zu beeinträchtigen.

Strategy:

// 1. Identify a Secondary
rs.status().members.forEach(m => {
  if (m.stateStr === "SECONDARY") {
    print(`Secondary: ${m.name}`)
  }
})

// 2. Optionally: Set priority to 0 (verhindert dass dieser Secondary Primary wird)
cfg = rs.conf()
cfg.members[2].priority = 0
cfg.members[2].hidden = true  // Versteckt von Clients
rs.reconfig(cfg)

// 3. Connect to Secondary und backup

Dann führe mongodump oder Filesystem-Snapshot auf dem Secondary aus. Der Primary ist nicht betroffen – Writes und Reads laufen normal.

Hidden-Members für Backups:

Eine Best-Practice ist ein dedicated Hidden-Member nur für Backups:

rs.add({ 
  host: "backup-node:27017",
  priority: 0,
  hidden: true,
  votes: 0  // Participiert nicht in Elections
})

Dieser Node repliziert Data from Primary, ist aber invisible to Clients und participiert nicht in Elections. Er existiert nur für Backups und Analytics-Queries.

Delayed-Members für Point-in-Time-Recovery:

Ein Delayed-Member repliziert Data mit einem Time-Delay – etwa 1 Stunde oder 24 Stunden:

rs.add({
  host: "delayed-node:27017",
  priority: 0,
  hidden: true,
  votes: 0,
  slaveDelay: 3600  // 1 hour delay
})

Wenn jemand versehentlich eine Collection dropt um 14:00, kann man um 14:30 zum Delayed-Member connecten, wo die Collection noch existiert (weil der Node 1 Stunde hinterher ist). Man kann die Data exportieren und zum Primary restoren.

Limitation:

Delayed-Members schützen nur gegen Human-Errors oder Software-Bugs, die sofort detektiert werden. Wenn ein Corruption-Bug langsam über Wochen Daten korrupt, hilft ein 1-Hour-Delayed-Member nicht.

45.5 Sharded-Cluster-Backups: Koordinierte Multi-Shard-Strategy

Sharded-Clusters sind komplex – Data ist über multiple Shards distributed, Metadata ist in Config-Servers. Ein konsistentes Backup erfordert Coordination.

Challenge:

Wenn man jeden Shard separat zu unterschiedlichen Zeiten backupt, ist das Backup inconsistent. Beispiel: - 10:00 AM: Backup Shard A - 10:30 AM: Backup Shard B - Zwischen 10:00 und 10:30: Ein Dokument moved von Shard A zu Shard B via Balancer

Das Dokument könnte in beiden Backups sein (duplicate) oder in keinem (verloren).

Solution 1: Stop Balancer:

// 1. Stop Balancer
sh.stopBalancer()

// 2. Backup Config-Servers (critical!)
mongodump --uri="mongodb://config-server:27019" --out=/backup/config

// 3. Backup each Shard (parallel möglich)
mongodump --uri="mongodb://shard1:27017" --out=/backup/shard1
mongodump --uri="mongodb://shard2:27017" --out=/backup/shard2

// 4. Start Balancer
sh.startBalancer()

Während Balancer gestoppt ist, bewegen sich keine Chunks – das Backup ist consistent.

Solution 2: Filesystem-Snapshots mit Coordination:

# 1. Stop Balancer
# 2. Flush all Shards und Config-Servers
# 3. Create Snapshots simultaneously (scripted)
# 4. Unlock and start Balancer

Config-Server-Backup ist kritisch:

Die Config-Servers enthalten Cluster-Metadata – welche Chunks auf welchem Shard, Shard-Ranges, etc. Ohne Config-Server-Backup kann man die Shard-Backups nicht korrekt restoren.

Restore-Process:

# 1. Restore Config-Servers first
mongorestore --uri="mongodb://config-server:27019" /backup/config

# 2. Restore each Shard
mongorestore --uri="mongodb://shard1:27017" /backup/shard1
mongorestore --uri="mongodb://shard2:27017" /backup/shard2

# 3. Restart mongos routers

45.6 Oplog-Backups: Point-in-Time-Recovery

Das Oplog (Operations-Log) ist das Replication-Journal – jede Write-Operation wird in Oplog logged. Durch Backup des Oplogs + einem Base-Backup kann man zu jedem Point-in-Time restoren.

Oplog-Backup with mongodump:

# Base Backup
mongodump --uri="mongodb://host:27017/mydb" --out=/backup/base-20240120

# Continuous Oplog Backup
mongodump --uri="mongodb://host:27017" --oplog --out=/backup/oplog-$(date +%Y%m%d-%H%M%S)

Der --oplog-Flag inkludiert Oplog-Entries seit Backup-Start bis Backup-End.

Point-in-Time-Restore:

# 1. Restore Base-Backup
mongorestore --uri="mongodb://host:27017" --drop /backup/base-20240120

# 2. Replay Oplog bis gewünschtem Timestamp
mongorestore --uri="mongodb://host:27017" --oplogReplay --oplogLimit="1705756800:0" /backup/oplog-*

Der --oplogLimit ist ein Timestamp (seconds:increment seit Epoch). MongoDB replayed alle Oplog-Entries bis zu diesem Point.

Use-Case:

Um 14:00 wird entdeckt, dass ein Bug seit 13:30 Daten korrupt. Man kann restoren zu 13:29:59 – dem letzten guten State.

Enterprise-Tools für Continuous-Backup:

MongoDB Atlas und Ops-Manager haben Continuous-Backup built-in – sie backupen Oplogs kontinuierlich und erlauben Point-in-Time-Restore via UI:

Atlas UI > Backups > Restore > Select timestamp: 2024-01-20 13:29:59

Für self-hosted MongoDB kann man Percona-Backup nutzen, das ähnliche Continuous-Backup-Capabilities hat.

45.7 Backup-Testing: Der kritischste Schritt

Ein Backup, das nie getestet wurde, ist potenziell wertlos. Die einzige Garantie, dass ein Backup funktioniert, ist successful Restore.

Testing-Strategy:

#!/bin/bash
# backup-test.sh

# 1. Create Backup
mongodump --uri="$PROD_URI" --out=/backup/test-$(date +%Y%m%d)

# 2. Provision Test-Server
# (Script oder Manual)

# 3. Restore to Test-Server
mongorestore --uri="$TEST_URI" --drop /backup/test-$(date +%Y%m%d)

# 4. Validate Restore
# - Connect to Test-Server
# - Run smoke-tests: Check collection counts, sample queries
TEST_COUNT=$(mongosh $TEST_URI --quiet --eval "db.users.countDocuments()")
PROD_COUNT=$(mongosh $PROD_URI --quiet --eval "db.users.countDocuments()")

if [ "$TEST_COUNT" -ne "$PROD_COUNT" ]; then
  echo "ERROR: Restore validation failed"
  exit 1
fi

echo "Backup-Test successful"

# 5. Cleanup
# Drop Test-Database oder Delete Test-Server

Dieses Script sollte regelmäßig laufen – etwa weekly oder monthly. Wenn es failed, ist das ein Alert – Backup-Strategy muss fixed werden.

Restore-Time-Testing:

Neben Correctness sollte man auch Restore-Time messen:

# Measure Restore-Time
START=$(date +%s)
mongorestore --uri="$TEST_URI" /backup/test-$(date +%Y%m%d)
END=$(date +%s)
DURATION=$((END - START))

echo "Restore took $DURATION seconds"

# Validate RTO
if [ "$DURATION" -gt 3600 ]; then  # RTO = 1 hour
  echo "WARNING: Restore exceeded RTO"
fi

Wenn Restore-Time steigt (etwa wegen Database-Growth), muss man Backup-Strategy anpassen.

45.8 Backup-Retention und Lifecycle

Backups sollten nicht forever retained werden – Storage ist teuer. Eine typische Retention-Policy:

Backup-Type Retention
Hourly 7 days
Daily 30 days
Weekly 90 days
Monthly 1 year
Yearly 7 years (Compliance)

Automated-Cleanup:

#!/bin/bash
# cleanup-old-backups.sh

BACKUP_DIR=/backup/mongodb

# Delete hourly backups older than 7 days
find $BACKUP_DIR/hourly -type d -mtime +7 -exec rm -rf {} \;

# Delete daily backups older than 30 days
find $BACKUP_DIR/daily -type d -mtime +30 -exec rm -rf {} \;

# Delete weekly backups older than 90 days
find $BACKUP_DIR/weekly -type d -mtime +90 -exec rm -rf {} \;

# Delete monthly backups older than 365 days
find $BACKUP_DIR/monthly -type d -mtime +365 -exec rm -rf {} \;

Dieses Script läuft täglich und cleaned expired Backups.

45.9 Backup-Encryption und Security

Backups enthalten sensitive Data – Passwords, PII, Financial-Data. Sie müssen encrypted und access-controlled sein.

Encryption-at-Rest:

# Encrypt Backup mit GPG
mongodump --uri="$MONGO_URI" --archive | gpg --encrypt --recipient backup@company.com > /backup/mongodb-$(date +%Y%m%d).archive.gpg

# Decrypt und Restore
gpg --decrypt /backup/mongodb-20240120.archive.gpg | mongorestore --archive

Oder Filesystem-Level-Encryption:

Wenn Backups auf encrypted Volumes gespeichert werden (LUKS, AWS-EBS-Encryption), sind sie automatisch encrypted.

Access-Control:

Backup-Files sollten restricted Permissions haben:

chmod 600 /backup/mongodb-*.bson  # Only Owner kann read/write

Für Cloud-Storage (S3, GCS):

# AWS S3 mit Server-Side-Encryption
aws s3 cp /backup/mongodb-20240120 s3://company-backups/mongodb/ --recursive --sse AES256

# Mit IAM-Policy: Nur Backup-Role kann access

45.10 Disaster-Recovery-Planning: Das Playbook

Ein Disaster-Recovery-Plan ist ein dokumentierter Workflow für Restore-Scenarios. Es sollte schritt-für-schritt Instructions enthalten, sodass jeder im Team (nicht nur der DBA) einen Restore durchführen kann.

Example-DR-Playbook:

# MongoDB Disaster Recovery Playbook

## Scenario 1: Accidental Data-Deletion

**Detection:** User reports missing data, confirmed in database

**Steps:**
1. Determine deletion time (check application logs)
2. Identify latest good backup before deletion
3. Provision temporary restore-server
4. Restore backup to temp-server
5. Export affected data from temp-server
6. Import data to production
7. Validate data integrity
8. Notify stakeholders

**Estimated Time:** 2 hours
**Required Access:** Production DB, Backup-Storage, Temp-Server

## Scenario 2: Database Corruption

**Detection:** MongoDB errors, failed queries, crashes

**Steps:**
1. Stop application traffic to database
2. Assess corruption extent (run db.repairDatabase())
3. If repair fails: Restore from latest backup
4. For replica-set: Restore to one member, re-sync others
5. Validate restored data
6. Resume application traffic
7. Conduct post-mortem

**Estimated Time:** 4 hours
**Required Access:** Production DB, Backup-Storage

## Scenario 3: Complete Datacenter Loss

**Detection:** All servers unreachable

**Steps:**
1. Activate DR-site or provision new infrastructure
2. Restore from off-site backups (S3, GCS)
3. Restore config-servers first (for sharded clusters)
4. Restore shards/replica-sets
5. Update DNS to point to new infrastructure
6. Resume application traffic
7. Monitor for issues

**Estimated Time:** 8-12 hours
**Required Access:** DR-site, Off-site backups, DNS-management

Dieses Playbook sollte regelmäßig geübt werden – etwa via Disaster-Recovery-Drills, wo man einen simulated Disaster durchspielt.

Die folgende Tabelle fasst Backup-Methods zusammen:

Method Speed Size Granularity Consistency Best-For
mongodump Slow Small Collection-Level Eventually Small DBs, Dev/Test
Filesystem-Snapshot Fast Full-Volume Database-Level Point-in-Time Large DBs, Production
Replica-Backup Medium Variable Database-Level Point-in-Time Replica-Sets
Oplog-Backup Continuous Incremental Point-in-Time Exact Enterprise, Zero-RPO
Cloud-Managed (Atlas) Automated Efficient Point-in-Time Exact Managed-MongoDB

Backups sind nicht glamorous – sie sind boring, repetitive, und hoffentlich niemals genutzt. Aber wenn der unthinkable-Disaster passiert, sind sie die einzige Rettung. Die Best-Practice ist Defense-in-Depth: Multiple-Backup-Methods (etwa Filesystem-Snapshots täglich + Oplog-Continuous), off-site-Backups (separate Datacenter oder Cloud-Region), encrypted-Backups, regelmäßiges Testing, documented-DR-Playbooks, und Practiced-Drills. Mit systematischem Backup-Management wird Data-Loss von catastrophic zu recoverable – nicht perfekt vermeidbar, aber manageable und boundable. Die Frage ist nicht “Werden wir jemals Backups brauchen” sondern “Wann werden wir Backups brauchen, und werden sie funktionieren”. Mit richtigem Backup-Design ist die Antwort: “Ja, sie werden funktionieren.”