Wenn Datenbankmigrationen eine eigene Pipeline benötigen
Sie haben eine solide CI/CD-Pipeline für Ihre Anwendung. Code wird gebaut, Tests laufen und Deployments erfolgen automatisch. Dann öffnet jemand einen Pull Request, der eine neue Spalte zur Benutzertabelle hinzufügt. Plötzlich fühlt sich die saubere Pipeline falsch an. Eine Datenbankmigration im selben Flow wie Anwendungscode auszuführen bedeutet entweder, das Deployment zu blockieren, bis die Migration abgeschlossen ist, oder die Migration separat auszuführen und zu hoffen, dass nichts kaputtgeht.
Das Problem ist, dass Datenbankänderungen sich anders verhalten als Anwendungscode. Ein fehlgeschlagener Build bedeutet lediglich kein neues Deployment. Eine fehlgeschlagene Migration kann Daten korrumpieren, Tabellen sperren oder Ihre Datenbank in einen inkonsistenten Zustand versetzen. Sie benötigen eine Pipeline, die für die spezifischen Risiken von Schemaänderungen, Daten-Backfills und Verifikation ausgelegt ist.
Warum Anwendungs-Pipelines nicht ausreichen
Anwendungs-Pipelines folgen einem einfachen Muster: Bauen, Testen, Deployen. Wenn ein Test fehlschlägt, stoppt die Pipeline. Wenn das Deployment fehlschlägt, beheben Sie das Problem und deployen erneut. Der Rollback ist normalerweise einfach das Deployment der vorherigen Version.
Datenbankmigrationen brechen dieses Modell. Eine Migration ändert die Struktur oder den Inhalt Ihrer Daten. Ein Rollback einer Migration ist nicht dasselbe wie das Rückgängigmachen einer Codeänderung. Sie müssen ein separates Skript ausführen, um die Schemaänderung rückgängig zu machen, und dieses Skript könnte fehlschlagen, wenn Daten bereits transformiert wurden. Sie müssen auch alte Datensätze mit neuen Werten befüllen (Backfill) und überprüfen, ob die Daten nach der Migration konsistent sind.
Der Versuch, Datenbankänderungen in dieselbe Pipeline wie Anwendungscode zu zwingen, führt zu Kompromissen. Entweder Sie überspringen automatisierte Tests für Migrationen, oder Sie führen sie manuell während Wartungsfenstern aus, oder Sie akzeptieren das Risiko, ungetestete Skripte in der Produktion auszuführen.
Eine separate Pipeline für Datenbankänderungen
Die Lösung besteht darin, eine dedizierte Pipeline für Datenbankänderungen zu erstellen, vollständig getrennt von Ihrer Anwendungs-Pipeline. Diese Pipeline hat eigene Stufen, eigene Freigabegates und eigenes Monitoring. Sie behandelt Datenbankänderungen als erstklassige Deployments, nicht als Nebeneffekte von Anwendungs-Releases.
So funktionieren die Stufen in der Reihenfolge.
Der folgende YAML-Ausschnitt zeigt, wie Sie diese Stufen in einem GitHub Actions-Workflow definieren könnten:
name: Database Migration Pipeline
on:
pull_request:
paths:
- 'migrations/**'
jobs:
dry-run:
runs-on: ubuntu-latest
steps:
- run: ./scripts/dry-run.sh
migration:
needs: dry-run
runs-on: ubuntu-latest
steps:
- run: ./scripts/migrate.sh
backfill:
needs: migration
runs-on: ubuntu-latest
steps:
- run: ./scripts/backfill.sh
reconciliation:
needs: backfill
runs-on: ubuntu-latest
steps:
- run: ./scripts/reconcile.sh
rollback-test:
needs: reconciliation
runs-on: ubuntu-latest
steps:
- run: ./scripts/rollback.sh
- run: ./scripts/reconcile.sh
Jeder Job läuft nur, wenn der vorherige Job erfolgreich war, und spiegelt den oben beschriebenen Pipeline-Flow wider.
Das folgende Flussdiagramm zeigt die fünf Stufen und ihren Fortschritt:
Stufe 1: Dry-Run
Jedes Mal, wenn ein neues Migrationsskript in Ihr Repository gelangt, führt die Pipeline einen Dry-Run gegen eine Staging-Datenbank durch. Das Skript wird ausgeführt, ändert aber nichts. Ziel ist es, Syntaxfehler, fehlende Abhängigkeiten oder Logikprobleme zu erkennen, bevor sie echte Daten berühren.
Wenn der Dry-Run fehlschlägt, stoppt die Pipeline sofort. Das Team erhält eine Benachrichtigung, und keine weiteren Stufen werden ausgeführt. Dies fängt die meisten häufigen Fehler frühzeitig ab, wenn sie günstig zu beheben sind.
Stufe 2: Migration
Nachdem der Dry-Run bestanden ist, führt die Pipeline die eigentliche Migration gegen die Staging-Datenbank durch. Dies ändert das Schema oder transformiert die Daten, aber immer noch in einer sicheren Umgebung. Die Pipeline protokolliert jeden Schritt: Startzeit, Endzeit, Anzahl der betroffenen Zeilen und alle Warnungen.
Diese Protokolle dienen als Prüfpfad. Wenn später etwas schiefgeht, können Sie genau nachvollziehen, was während der Migration passiert ist. Sie haben auch eine Aufzeichnung darüber, wie lange jeder Schritt gedauert hat, was Ihnen hilft, die Laufzeiten in der Produktion abzuschätzen.
Stufe 3: Backfill
Einige Migrationen erfordern das Befüllen von Daten für vorhandene Datensätze. Das Hinzufügen einer neuen Spalte mit einem Standardwert könnte beispielsweise Millionen vorhandener Zeilen aktualisieren. Dies als ein massives Update auszuführen, kann die Tabelle für Minuten oder Stunden sperren.
Die Pipeline führt Backfills in kleinen Batches durch, typischerweise tausend Zeilen pro Iteration, mit einer kurzen Pause zwischen den Batches. Dies hält die Datenbank reaktionsfähig und reduziert das Risiko langlaufender Sperren. Die Pipeline überwacht jeden Batch auf Dauer und Fehlerrate. Wenn ein Batch fehlschlägt, stoppt die Pipeline und sendet einen Alarm. Sie wiederholt nicht automatisch, da der Fehler auf ein tieferes Problem hinweisen könnte, das untersucht werden muss.
Stufe 4: Reconciliation
Nachdem die Migration und der Backfill abgeschlossen sind, führt die Pipeline ein Reconciliation-Skript aus. Dies vergleicht die Daten vor und nach der Migration. Der Vergleich kann Zeilenanzahlen, Prüfsummen auf bestimmten Spalten oder aggregierte Werte wie Gesamtsalden in einer Transaktionstabelle überprüfen.
Wenn die Reconciliation unerwartete Unterschiede feststellt, schlägt die Pipeline fehl. Das Team muss nachforschen, bevor es fortfährt. Diese Stufe erkennt stille Datenkorruption, partielle Updates oder Logikfehler, die keinen Absturz verursacht haben, aber dennoch falsche Ergebnisse produziert haben.
Stufe 5: Rollback-Test
Die Pipeline führt das Rollback-Skript aus, um zu überprüfen, ob die Migration sauber rückgängig gemacht werden kann. Nach dem Rollback führt sie erneut eine Reconciliation durch, um zu bestätigen, dass die Daten in ihren ursprünglichen Zustand zurückgekehrt sind.
Dies ist die wichtigste Stufe, um Vertrauen aufzubauen. Wenn der Rollback-Test im Staging bestanden wird, wissen Sie, dass Sie die Migration in der Produktion sicher rückgängig machen können, falls etwas schiefgeht. Wenn er fehlschlägt, stoppt die Pipeline, und die Migration darf nicht in die Produktion gehen.
Ausführung in der Produktion
Nachdem alle fünf Stufen im Staging bestanden sind, ist die Pipeline bereit für die Produktion. Aber der Prozess ist nicht automatisch. Ein manueller Freigabeschritt sitzt zwischen Staging und Produktion. Jemand mit Datenbankkenntnissen überprüft die Ergebnisse und genehmigt den Produktionslauf.
In der Produktion führt die Pipeline dieselbe Sequenz aus: Dry-Run, Migration, Backfill, Reconciliation und Rollback-Test. Der Unterschied ist, dass das Monitoring strenger ist und die Pipeline mitten in einer Stufe gestoppt werden kann, wenn Anomalien auftreten. Jede Stufe in der Produktion hat auch ihre eigene Rollback-Fähigkeit, sodass Sie jederzeit abbrechen können, ohne die Datenbank in einem defekten Zustand zu hinterlassen.
Praktische Checkliste für Ihre Datenbank-Pipeline
- Datenbank-Pipeline von der Anwendungs-Pipeline trennen
- Immer einen Dry-Run vor der eigentlichen Migration durchführen
- Jeden Schritt mit Zeitstempeln und Zeilenanzahlen protokollieren
- Backfills in kleinen Batches mit Monitoring durchführen
- Reconciliation-Prüfungen nach Migration und Backfill hinzufügen
- Rollback-Skripte vor der Produktion im Staging testen
- Manuelle Freigabe für Produktionsläufe verlangen
- Die Fähigkeit behalten, die Pipeline mitten in einer Stufe zu stoppen
Das Fazit
Datenbankmigrationen verdienen dieselbe Sorgfalt wie Anwendungs-Deployments. Eine dedizierte Pipeline mit Dry-Run-, Backfill-, Reconciliation- und Rollback-Test-Stufen gibt Ihnen das Vertrauen, dass Schemaänderungen Ihre Daten nicht stillschweigend korrumpieren. Die zusätzlichen Stufen verlängern die Zeit für jede Migration, aber sie sparen weit mehr Zeit, indem sie Produktionsvorfälle und die hektische Wiederherstellungsarbeit danach verhindern. Behandeln Sie Ihre Datenbankänderungen wie Produktions-Deployments, und Ihre Daten bleiben bei jedem Update konsistent.