CI/CD
.yml
GitLab · Magento · Datenbank-Backup · DB-Rollback · Deployment-Sicherheit
Zero-Downtime und Datenbank-Backups:
Wann vor dem Release gesichert werden muss

Ein Symlink-Rollback reicht nicht immer. Wenn Datenbankmigrationen Teil des Deployments sind, muss ein aktuelles DB-Backup existieren – bevor der erste Migrationschritt ausgeführt wird, nicht danach.

11 Min. Lesezeit mysqldump · Percona XtraBackup · GitLab Pipeline · DB-Rollback · Backup-Verifikation Magento 2.4 · MySQL 8 · GitLab CI/CD

1. Warum ein Symlink-Rollback allein nicht ausreicht

Der Symlink-Rollback in Magento-Deployments ist schnell und sicher für die Codeebene. Er wechselt den current-Symlink zurück auf ein älteres Release-Verzeichnis und stellt damit den alten Code sofort wieder her. Was er nicht kann: Datenbankänderungen rückgängig machen. Wenn setup:upgrade im neuen Release Tabellen verändert, Spalten hinzugefügt oder Konfigurationsdaten geschrieben hat, existieren diese Änderungen in der Datenbank – auch nach einem Code-Rollback.

Das Resultat eines Symlink-Rollbacks ohne DB-Rollback bei schemaändernden Migrationen: Der alte Code läuft mit dem neuen Datenbankschema. Je nach Art der Migration kann das harmlos sein (additive Spalten, die der alte Code ignoriert) oder kritisch (geänderte Spaltennamen oder -typen, auf die der alte Code zuzugreifen versucht). Ohne ein aktuelles Datenbankbackup gibt es keine Möglichkeit, einen konsistenten Zustand aus altem Code und alter Datenbank wiederherzustellen.

Der Backup-Job in der GitLab-Pipeline ist deshalb kein optionales Nice-to-have, sondern ein expliziter Sicherheitsschritt für jeden Release mit Datenbankmigrationen. Er muss vor dem Migrations-Schritt ausgeführt werden, nicht danach. Ein Backup, das nach einer fehlgeschlagenen Migration erstellt wird, sichert den kaputten Zustand, nicht den sauberen Ausgangszustand.

2. Wann ein Backup vor dem Release Pflicht ist

Ein Datenbank-Backup vor dem Release ist Pflicht, wenn das Release eine oder mehrere der folgenden Bedingungen erfüllt: Es enthält Datenbankmigrationen (Setup/Patch/Schema-Dateien in eigenen Modulen oder Magento-Core-Updates). Es enthält setup:upgrade-Aufrufe, die das Datenbankschema verändern. Es enthält Datentransformationen, die bestehende Datensätze modifizieren oder löschen. Es enthält Konfigurationsänderungen, die Datenbankeinträge in der core_config_data-Tabelle anlegen oder modifizieren.

Ein Backup ist optional, aber empfohlen, bei reinen Code-Releases ohne Datenbankinteraktion. Selbst hier kann ein Backup sinnvoll sein, wenn das Release auf einem System deployt wird, das keine zuverlässige automatische Backup-Infrastruktur hat. Der Grundsatz gilt: Kein Deploy auf Production ohne bekannten, verifizierten Backup-Zeitpunkt. Das Backup muss nicht zwingend im Deploy-Moment erstellt werden – ein verifizierbares Backup aus den letzten Stunden kann für reine Code-Releases ausreichen.

3. Backup-Methoden: mysqldump vs. Percona XtraBackup

mysqldump ist das Standard-Werkzeug für MySQL-Backups in Magento-Deployments. Es erzeugt eine SQL-Dump-Datei, die alle Tabellen, Daten und Indexe enthält. Nachteile: Bei großen Magento-Datenbanken (mehrere Gigabyte) kann mysqldump mehrere Minuten dauern und während dieser Zeit erhöhte Datenbanklast erzeugen. Mit dem --single-transaction-Flag wird der Dump innerhalb einer Transaktion durchgeführt, was konsistente Daten ohne Table-Locks gewährleistet – vorausgesetzt, alle Tabellen nutzen InnoDB.

Percona XtraBackup erstellt Hot-Backups ohne den normalen Datenbankbetrieb zu unterbrechen und ist für große Produktionsdatenbanken deutlich schneller. Für Magento-Setups mit Datenbanken unter 5 GB ist mysqldump --single-transaction in der Regel ausreichend und einfacher zu konfigurieren. Für größere Datenbanken oder Hochverfügbarkeits-Setups ist XtraBackup die professionellere Wahl. Die Entscheidung hängt von der Datenbankgröße und den akzeptablen Backup-Zeiten im Deployment-Fenster ab.

# Database backup job — runs before any deployment with DB migrations
backup:database:
  stage: deploy
  variables:
    # Backup retention: keep 7 release backups
    BACKUP_DIR: "/var/backups/magento/releases"
    BACKUP_RETENTION: "7"
  script:
    - eval $(ssh-agent -s)
    - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
    - echo "$SSH_KNOWN_HOSTS" > ~/.ssh/known_hosts
    - BACKUP_TS=$(date +%Y%m%d-%H%M%S)
    - BACKUP_FILE="magento-pre-release-$BACKUP_TS.sql.gz"
    - |
      ssh "$DEPLOY_USER@$DEPLOY_HOST" bash -s << SSH
      set -euo pipefail
      mkdir -p "$BACKUP_DIR"
      cd "$DEPLOY_PATH/current"
      # Read DB credentials from Magento env.php
      DB_HOST=\$(php -r "
        \\\$env = include 'app/etc/env.php';
        echo \\\$env['db']['connection']['default']['host'];
      ")
      DB_NAME=\$(php -r "
        \\\$env = include 'app/etc/env.php';
        echo \\\$env['db']['connection']['default']['dbname'];
      ")
      DB_USER=\$(php -r "
        \\\$env = include 'app/etc/env.php';
        echo \\\$env['db']['connection']['default']['username'];
      ")
      DB_PASS=\$(php -r "
        \\\$env = include 'app/etc/env.php';
        echo \\\$env['db']['connection']['default']['password'];
      ")
      # Create consistent backup using single transaction (InnoDB safe)
      mysqldump \
        --host="\$DB_HOST" \
        --user="\$DB_USER" \
        --password="\$DB_PASS" \
        --single-transaction \
        --quick \
        --routines \
        --triggers \
        --add-drop-table \
        "\$DB_NAME" | gzip -9 > "$BACKUP_DIR/$BACKUP_FILE"
      echo "Backup created: $BACKUP_DIR/$BACKUP_FILE"
      ls -lh "$BACKUP_DIR/$BACKUP_FILE"
      SSH
  needs: []
  when: manual
  only:
    - tags

5. Backup-Verifikation: Das Backup wirklich prüfen

Ein Backup, das nicht verifiziert wurde, ist kein Backup – es ist eine Datei mit unbekanntem Inhalt. Die Verifikation eines mysqldump-Backups besteht aus zwei Ebenen. Die erste Ebene ist die Dateiintegrität: Prüfsumme berechnen und speichern, Dateigröße plausibilisieren (ein komprimiertes Backup kleiner als 1 MB ist für eine Magento-Produktionsdatenbank verdächtig). Die zweite Ebene ist die inhaltliche Prüfung: Die komprimierte SQL-Datei mit gunzip -t auf Komprimierungsintegrität prüfen, die ersten Zeilen der Dump-Datei auf SQL-Header prüfen.

Eine vollständige Restore-Verifikation – Backup in eine Test-Datenbank einspielen und auf Vollständigkeit prüfen – ist für produktive Release-Pipelines zu aufwändig. Sie sollte als separater, regelmäßig ausgeführter Job existieren, nicht als Teil des Deployment-Prozesses. Was im Deployment-Prozess ausreicht: Dateiintegrität, Komprimierungsintegrität und eine plausible Dateigröße. Diese drei Checks dauern Sekunden und schützen vor den häufigsten Backup-Fehlern (leere Datei, abgebrochener Dump, Kompressionsfehler).

6. Backup-Timing: Unmittelbar vor der Migration

Das Backup muss unmittelbar vor dem Migrations-Schritt erstellt werden. Eine Stunde zwischen Backup und Migration ist in einem aktiven Produktionssystem keine akzeptable Lücke – in dieser Zeit können tausende Bestellungen, Kundendaten und Konfigurationsänderungen in die Datenbank geschrieben worden sein. Ein Rollback auf ein Backup von vor einer Stunde bedeutet den Verlust dieser Daten.

In der GitLab-Pipeline wird das Timing durch die Job-Reihenfolge und die needs-Direktive erzwungen: Der Backup-Job muss als direktes Prerequisite des Migrations-Jobs definiert sein. Kein Migrations-Job darf starten, bevor der Backup-Job erfolgreich abgeschlossen wurde. Diese Abhängigkeit schützt vor dem häufigsten Fehler: dem Backup, das erst nach einem Problem erstellt wird, wenn die Datenbank bereits in einem beschädigten Zustand ist.

# Deploy pipeline with mandatory backup before DB migration
stages:
  - build
  - test
  - backup    # Backup stage runs before deploy
  - deploy
  - verify
  - rollback

# Backup job — must complete before any deploy with DB migration
backup:pre-release:
  stage: backup
  script:
    - eval $(ssh-agent -s)
    - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
    - echo "$SSH_KNOWN_HOSTS" > ~/.ssh/known_hosts
    - BACKUP_TS=$(date +%Y%m%d-%H%M%S)
    - |
      ssh "$DEPLOY_USER@$DEPLOY_HOST" bash -s << 'SSH'
      set -euo pipefail
      BACKUP_FILE="/var/backups/magento/releases/pre-release-$BACKUP_TS.sql.gz"
      mkdir -p /var/backups/magento/releases
      # Run backup using credentials from env.php
      cd "$DEPLOY_PATH/current"
      php bin/magento setup:backup --db
      # Also create external backup for faster restore
      mysqldump --defaults-file=/etc/mysql/backup.cnf \
        --single-transaction --quick --routines --triggers \
        magento | gzip -9 > "$BACKUP_FILE"
      # Verify backup integrity
      gunzip -t "$BACKUP_FILE" && echo "Backup integrity OK"
      ls -lh "$BACKUP_FILE"
      # Record backup location for rollback job
      echo "$BACKUP_FILE" > /var/backups/magento/latest-pre-release.txt
      SSH
  when: manual
  only:
    - tags

# Deploy job must explicitly wait for backup
deploy:production:with-migration:
  stage: deploy
  needs:
    - backup:pre-release  # Cannot start without successful backup
  script:
    - echo "Backup verified — starting deployment with DB migration"
    # ... deploy steps with setup:upgrade
  when: manual
  only:
    - tags

7. DB-Rollback: Wie ein Datenbank-Rollback abläuft

Ein Datenbank-Rollback ist teurer als ein Code-Rollback und sollte deshalb nur ausgeführt werden, wenn der Code-Rollback allein nicht ausreicht. Die Entscheidung muss schnell getroffen werden: Wenn das Deployment fehlgeschlagen ist und die Datenbank in einem inkonsistenten Zustand ist, zählt jede Minute. Der DB-Rollback-Prozess muss dokumentiert, geübt und durch ein Skript automatisiert sein, damit er auch unter Druck korrekt ausgeführt werden kann.

Der Ablauf eines DB-Rollbacks: Maintenance-Mode aktivieren, um weitere Datenbankschreibvorgänge zu verhindern. Code-Rollback durchführen (Symlink zurück auf vorheriges Release). Datenbank aus dem Pre-Release-Backup wiederherstellen. Backup-Restore verifizieren (Tabellenzahl, kritische Konfigurationswerte prüfen). Maintenance-Mode deaktivieren. Der gesamte Prozess dauert bei einem mysqldump-basierten Backup typischerweise 5–15 Minuten, abhängig von der Datenbankgröße.

8. Backup-Aufbewahrung und Rotation

Pre-Release-Backups müssen nicht unbegrenzt aufbewahrt werden, aber sie müssen so lange verfügbar sein, wie ein Rollback noch sinnvoll möglich ist. Eine Aufbewahrungszeit von 7 Release-Backups ist für die meisten Magento-Projekte ausreichend: Sie deckt die letzten sieben Deployments ab, was typischerweise mehrere Wochen entspricht. Ältere Backups werden automatisch rotiert, um Speicherplatz zu sparen.

Die Rotation sollte als Teil des Backup-Jobs implementiert werden, nicht als separaten Cron-Job: Unmittelbar nach dem Erstellen des neuen Backups werden alle Backups außer den letzten sieben gelöscht. Das hält den Speicher kontrolliert und vermeidet die Situation, in der der Backup-Speicher vollläuft und neue Backups nicht mehr erstellt werden können. Die Dateigröße der Backups sollte ebenfalls protokolliert werden, damit ungewöhnliche Größenänderungen als Anomalie erkannt werden.

9. Mit vs. ohne Backup-Job: direkter Vergleich

Der Unterschied zwischen einem Deployment-Prozess mit und ohne Backup-Job zeigt sich ausschließlich im Störfall. In normalen Deployments wird das Backup nie benötigt. Im Störfall – einem fehlgeschlagenen Migrations-Schritt, einer beschädigten Datenbank oder einem unerwarteten Code-Fehler mit Datenbankkorrumpierung – ist das Backup der einzige Weg zurück zu einem konsistenten Zustand.

Szenario Ohne Backup-Job Mit Backup-Job (Pipeline) Konsequenz
Migration schlägt fehl Kein Rollback möglich DB-Restore aus Backup 5–15 Min. Restore vs. unbegrenzte Downtime
Code-Rollback bei DB-Migration Inkonsistenter Zustand Code + DB konsistent zurück Sauberer Ausgangszustand wiederhergestellt
Backup-Zeitpunkt Letztes nächtliches Backup Unmittelbar vor Migration Datenverlust minimal vs. stundenlang
Backup-Verifikation Unbekannt Integrität geprüft Backup funktioniert garantiert
Rollback-Dauer Stunden oder unmöglich 5–15 Minuten Planbar, vorhersehbar, kommunizierbar

Die Kosten des Backup-Jobs sind gering: Der mysqldump-Befehl mit --single-transaction dauert bei einer typischen Magento-Datenbank (1–5 GB) zwischen 1 und 5 Minuten. Das ist eine überschaubare Investition in die Fähigkeit, im Störfall kontrolliert reagieren zu können. Ein Deployment ohne Backup ist eine Wette darauf, dass alles gutgeht. Ein Deployment mit Backup ist ein kontrollierter Prozess.

10. Zusammenfassung

Datenbank-Backups vor Magento-Releases sind nicht optional für Deployments mit Datenbankmigrationen. Sie sind die einzige Absicherung gegen Datenverlust bei einem fehlgeschlagenen Migrations-Schritt. Das Backup muss unmittelbar vor der Migration erstellt werden, seine Integrität muss verifiziert werden, und es muss als explizites Prerequisite des Migrations-Jobs in der GitLab-Pipeline definiert sein.

Der DB-Rollback-Prozess muss dokumentiert, geübt und durch Skripte automatisiert sein. Im Störfall entscheiden Minuten über den Umfang des Schadens. Ein Team, das den DB-Rollback-Prozess erst im Störfall zum ersten Mal ausführt, ist nicht vorbereitet. Ein Team, das ihn regelmäßig auf Staging übt und durch die Pipeline automatisiert hat, kann auch unter Druck kontrolliert handeln. Das ist der Kern von Zero-Downtime-Design: nicht die Hoffnung, dass nichts schiefgeht, sondern die Vorbereitung auf den Fall, dass etwas schiefgeht.

Datenbank-Backups für Magento-Releases — Das Wichtigste auf einen Blick

Wann Pflicht

Bei allen Releases mit Datenbankmigrationen: setup:upgrade, eigene Schema-Patches, Core-Updates.

Backup-Methode

mysqldump --single-transaction für InnoDB-Tabellen. Für große DBs: Percona XtraBackup. Integrität immer prüfen.

Pipeline-Integration

Backup-Job als needs-Prerequisite des Migrations-Jobs. Kein Deploy ohne erfolgreich abgeschlossenen Backup-Job.

DB-Rollback

Maintenance → Code-Rollback → DB-Restore aus Pre-Release-Backup → Verify → Maintenance off. Prozess dokumentiert und geübt.

11. FAQ: Datenbank-Backups vor Magento-Releases

1Muss vor jedem Deploy ein DB-Backup erstellt werden?
Bei Deployments mit DB-Migrationen: zwingend ja. Bei reinen Code-Releases: empfohlen, aber nicht zwingend wenn ein aktuelles automatisches Backup existiert.
2Warum reicht ein nächtliches Backup nicht?
Zwischen nächtlichem Backup und Deploy werden Stunden an Bestellungen, Kundendaten und Konfigurationsänderungen geschrieben. Rollback auf nächtliches Backup bedeutet Datenverlust.
3--single-transaction vs. Table-Locks?
--single-transaction: kein Table-Lock, Dump in einer Transaktion, unterbricht Betrieb nicht. Voraussetzung: alle Tabellen InnoDB. Ohne: Tabellen werden gesperrt.
4Wie lange dauert mysqldump für Magento?
1–5 Minuten für 1–5 GB. Percona XtraBackup für Datenbanken über 10 GB deutlich schneller.
5Symlink-Rollback ohne DB-Rollback ausreichend?
Nur bei additiven Migrationen (neue Spalten). Bei destruktiven Änderungen (Spalten umbenannt/gelöscht) ist DB-Rollback notwendig.
6Was prüft gunzip -t?
Komprimierungsintegrität: Vollständigkeit, korrekte Checksummen, Dateistruktur. Stellt sicher, dass der Dump nicht abgebrochen wurde und die Datei wiederherstellbar ist.
7Wie viele Pre-Release-Backups aufbewahren?
Sieben Release-Backups – deckt typischerweise mehrere Wochen ab. Automatische Rotation, um Speicher zu kontrollieren.
8Wie lange dauert ein vollständiger DB-Rollback?
5–15 Minuten für Restore bei 1–5 GB. Gesamter Prozess (Maintenance → Code-Rollback → DB-Restore → Verify) 10–20 Minuten.
9Backup-Job automatisch oder manuell?
Automatisch als Pflicht-Prerequisite des Migrations-Jobs. Kein Migrations-Job darf ohne abgeschlossenen Backup-Job starten.
10bin/magento setup:backup vs. mysqldump?
setup:backup ist einfach zu verwenden. mysqldump mit --single-transaction ist für Produktion mit großen DBs flexibler und beim Restore schneller.