Bereitschaft für Datenbankmigrationen bei selbstgehosteten Anwendungen: Können Sie sicher zurückrollen?
Nutzen Sie diese Checkliste zum Zurückrollen von Datenbankmigrationen, bevor Sie eine selbstgehostete Anwendung aktualisieren. Trennen Sie Code-Rollback von Datenbankwiederherstellung, bewerten Sie Kompatibilität und Sperren, prüfen Sie Backups und legen Sie Wiederherstellungsentscheidungen vor der Bereitstellung fest.

Warum Anwendungs-Rollback und Datenbank-Rollback verschieden sind
Das Ersetzen eines neuen Anwendungscontainers durch das vorherige Image kann schnell gehen. Das ist ein Code-Rollback. Es stellt die Datenbank jedoch nicht automatisch auf die Struktur und Inhalte zurück, die von der früheren Version erwartet werden.
Eine Datenbankmigration kann Tabellen hinzufügen, Spalten umbenennen, gespeicherte Werte umwandeln, Indizes erstellen, Constraints verschärfen, Daten löschen oder Arbeiten starten, die nach der Bereitstellung fortgesetzt werden. Sobald eine Migration festgeschrieben wurde, ist ein ROLLBACK auf Transaktionsebene für diese festgeschriebene Arbeit nicht mehr verfügbar. Eine sichere Wiederherstellung kann stattdessen das Wiederherstellen von Daten, die Datenreparatur oder die Umsetzung einer Vorwärtskorrektur erfordern.
Behandeln Sie die Anwendungsversion und die Datenbankänderung als zwei miteinander verbundene, aber getrennte Bereitstellungsobjekte. Die Freigabe sollte davon abhängen, ob die alte Anwendung sicher mit dem Datenbankzustand nach der Migration arbeiten kann, nicht nur davon, ob ein älteres Container-Image verfügbar ist.
- Frage zum Code-Rollback: Kann die frühere Anwendungsversion gestartet und wieder in Betrieb genommen werden?
- Frage zur Datenbankwiederherstellung: Können das frühere Schema und die erforderlichen Geschäftsdaten ohne inakzeptablen Verlust wiederhergestellt oder rekonstruiert werden?
- Kompatibilitätsfrage: Können alter Code, neuer Code und die geänderte Datenbank während des geplanten Übergangs gleichzeitig bestehen?
- Entscheidungsregel: Beschreiben Sie eine Version erst dann als reversibel, wenn sowohl der Code- als auch der Datenbankpfad geprüft wurden.

Erfassen Sie vor der Freigabe jede datenbankwirksame Änderung
Erstellen Sie eine Änderungsübersicht auf Basis der Release Notes der Anwendung, der Migrationsdateien, Bereitstellungsskripte und Datenbankbefehle. Verlassen Sie sich nicht auf eine Bezeichnung wie „automatische Migration“; ermitteln Sie, was diese Automatisierung tatsächlich ändert und wann sie ausgeführt wird.
Klassifizieren Sie jeden Vorgang nach seiner Auswirkung auf Schema, Daten, Verfügbarkeit und Reversibilität. Das Ziel ist nicht, jedes Implementierungsdetail vorherzusagen. Es geht darum, Vorgänge sichtbar zu machen, die die Wiederherstellungsstrategie verändern oder betriebliche Kontrollen erfordern.
Identifizieren Sie bei containerisierten Bereitstellungen außerdem, wo persistente Datenbankdaten liegen. Docker-Compose-Volumes sind persistente Speicher, die von der Container-Engine verwaltet werden. Daher müssen das Datenbank-Volume, ein möglicher externer Datenbankdienst und die Backup-Quelle eindeutig sein. Das Neuerstellen eines Anwendungs-Workloads ist kein Nachweis dafür, dass die Datenbank erhalten geblieben ist.
- Schema: neue oder entfernte Tabellen, Spalten, Typen, Indizes, Fremdschlüssel, Standardwerte und Constraints.
- Datentransformation: Backfills, Wertkonvertierungen, Deduplizierung, Änderungen der Verschlüsselung, Umschreiben von Kennungen und Löschungen.
- Leistung und Sperren: Umschreiben von Tabellen, Indexaufbauten, lang laufende Abfragen und Vorgänge, die auf andere Transaktionen warten können.
- Hintergrundarbeit: eingereihte Jobs, Worker, geplante Aufgaben oder Aufgaben beim Anwendungsstart, die Daten nach der Schemamigration weiter verändern.
- Abhängigkeiten: Reporting-Tools, Integrationen, Exporte, Views, API-Konsumenten und benutzerdefinierte Skripte, die auf vorhandene Felder oder Werte angewiesen sein können.
- Migrationsmetadaten: die Migrationskennung, Ausführungsreihenfolge, das Tool oder Framework und ob jeder Schritt über eine dokumentierte Umkehroperation verfügt.

Prüfen Sie Rückwärts- und Vorwärtskompatibilität ausdrücklich
Eine sichere Bereitstellung hängt häufig von einem Kompatibilitätsfenster ab: einem Zeitraum, in dem sowohl die vorherige als auch die neue Anwendungsversion denselben Datenbankzustand verwenden kann. Ohne dieses Fenster kann ein Code-Rollback nach der Migration fehlschlagen, selbst wenn das alte Image normal startet.
Prüfen Sie Lese- und Schreibverhalten getrennt. Alter Code kann eine neue nullable Spalte tolerieren, aber fehlschlagen, wenn eine von ihm beschriebene Spalte entfernt, umbenannt, verpflichtend gemacht oder in ihrer Bedeutung verändert wurde. Neuer Code kann vor Abschluss eines Backfills nur dann starten, wenn er alte und neue Repräsentationen korrekt verarbeiten kann.
Machen Sie Kompatibilität zu einer dokumentierten Entscheidung statt zu einer Annahme. Wenn alter Code nicht mit der migrierten Datenbank kompatibel ist, muss der Wiederherstellungsplan einer Wiederherstellung, Datenreparatur oder Vorwärtskorrektur Vorrang vor einem einfachen Code-Rollback geben.
- Alter Code mit erweitertem Schema: Kann er zusätzliche Tabellen, Spalten und Indizes ignorieren?
- Neuer Code vor Abschluss der Datenmigration: Kann er sowohl alte als auch neue Werteformate lesen?
- Alter Code nach einem Backfill: Wird er transformierte Daten überschreiben oder Datensätze in einem veralteten Format anlegen?
- Zeitpunkt von Constraints: Wird ein neues NOT-NULL-, Eindeutigkeits- oder Fremdschlüssel-Constraint Schreibvorgänge einer älteren Version ablehnen?
- Externe Konsumenten: Hängen Integrationen von einem durch die Änderung betroffenen Spaltennamen, Ausgabeformat, einer Kennung oder einem API-Verhalten ab?
- Betrieb gemischter Versionen: Wird ein gleichzeitiger Betrieb alter und neuer Versionen unterstützt, wenn mehrere Anwendungs-Worker schrittweise neu gestartet werden?
Kennzeichnen Sie destruktive Vorgänge und sperrsensitive Änderungen
Einige Änderungen verdienen einen ausdrücklichen Wiederherstellungsplan, weil sie Informationen entfernen, frühere Annahmen ungültig machen oder die Verfügbarkeit beeinträchtigen. Das Löschen einer PostgreSQL-Spalte kann auch Indizes und Tabellen-Constraints entfernen, die diese Spalte betreffen; Abhängigkeiten außerhalb der Tabelle, etwa Fremdschlüssel oder Views, können weitere Maßnahmen erfordern. Eine destruktive Änderung darf nie allein deshalb freigegeben werden, weil sie spät in einer Migrationssequenz erscheint.
Die Auswirkungen von Sperren sind ebenso wichtig. Bei PostgreSQL unterscheiden sich die Sperranforderungen von ALTER TABLE je nach Unterbefehl, und ACCESS EXCLUSIVE ist der Standard, sofern die Dokumentation nichts anderes angibt. Prüfen Sie die genauen Anweisungen, statt jeden ALTER-TABLE-Vorgang als gleichwertig zu behandeln.
Auch die Indexerstellung erfordert eine Bereitstellungsentscheidung. Ein gewöhnlicher PostgreSQL-Indexaufbau blockiert Schreibvorgänge während seiner Ausführung. CREATE INDEX CONCURRENTLY vermeidet das Blockieren paralleler Inserts, Updates und Deletes, kann aber nicht innerhalb eines Transaktionsblocks ausgeführt werden, führt zusätzliche Tabellenscans durch und wartet auf relevante Transaktionen. Das verändert sowohl Timing als auch Fehlerbehandlung.
ALTER-TABLE-Varianten, die Tabellen umschreiben, sowie TRUNCATE benötigen bei gleichzeitigem Zugriff eine besonders sorgfältige Prüfung. PostgreSQL dokumentiert MVCC-Einschränkungen für diese Vorgänge, einschließlich Fällen, in denen parallele Snapshots nach dem Commit eine leere oder inkonsistente Ansicht sehen können.
- Destruktiv: DROP COLUMN, DROP TABLE, TRUNCATE, Lösch-Backfills, irreversible Wertkonvertierungen und das Ersetzen von Kennungen.
- Kompatibilitätsbrechend: Umbenennung oder Entfernung eines von altem Code verwendeten Feldes, Verschärfung eines Constraints und Änderung der Bedeutung gespeicherter Werte.
- Verfügbarkeitssensitiv: Tabellenumschreibungen, sperrintensive ALTER-TABLE-Vorgänge und gewöhnliche Indexaufbauten auf aktiv beschriebenen Tabellen.
- Schritte außerhalb einer einzelnen Transaktion: gleichzeitige Indexerstellung und Hintergrundarbeit, die außerhalb einer Transaktionsgrenze stattfinden.
- Erforderliche Reaktion: Benennen Sie vor der Bereitstellung für jeden gekennzeichneten Vorgang die genaue Wiederherstellungsmethode.
Bevorzugen Sie Expand, Migrate, Contract, wenn die Anwendung dies unterstützt
Nutzen Sie für wesentliche Änderungen ein Expand–Migrate–Contract-Muster, sofern die Anwendung und die Herstelleranleitung dies unterstützen. Dadurch werden Kompatibilitätsarbeiten von destruktiver Bereinigung getrennt und es entsteht Raum, Code zu validieren und zurückzurollen, bevor irreversible Änderungen eingeführt werden.
Expand bedeutet, neue Strukturen hinzuzufügen, ohne die alten zu entfernen: beispielsweise ein neues nullable Feld, eine Tabelle oder einen Index. Migrate bedeutet, Daten per Backfill zu füllen und der neuen Anwendungsversion beizubringen, die kompatible Repräsentation zu lesen und zu schreiben. Contract bedeutet, veraltete Strukturen erst zu entfernen, nachdem das Kompatibilitätsfenster beendet und die Validierung abgeschlossen ist.
Erzwingen Sie dieses Muster nicht für eine Anwendung, deren bereitgestellter Migrationspfad keine gestuften Versionen unterstützt. Dokumentieren Sie in diesem Fall die vom Hersteller geforderte Reihenfolge, testen Sie sie genau so und wählen Sie einen angemessenen Wartungs- und Wiederherstellungsplan. Das nützliche Prinzip ist die Trennung von Risiken, nicht eine künstliche Überarbeitung von Drittanbieter-Migrationen.
- Expand: Fügen Sie die neue Struktur hinzu und bestätigen Sie, dass alter Code weiterhin funktioniert.
- Kompatiblen Code bereitstellen: Stellen Sie sicher, dass neuer Code bei Bedarf beide Repräsentationen verarbeitet.
- Migrate: Führen Sie Backfills, soweit die Anwendung diesen Ansatz unterstützt, in beobachtbaren Batches aus.
- Validieren: Vergleichen Sie Anzahlen, erforderliche Datensätze, Berechtigungen, Integrationen und wichtige Workflows.
- Contract: Entfernen Sie Alt-Felder oder -Formate erst, nachdem das Rollback-Fenster bewusst geschlossen wurde.
- Punkt ohne Rückkehr dokumentieren: Geben Sie genau an, wann ein einfacher Code-Rollback nicht mehr sicher ist.
Sammeln Sie Bereitstellungsnachweise, nicht nur einen Backup-Status
Ein Backup ist nur dann nützlich, wenn Methode, Abdeckung, Speicherort und Wiederherstellungsprozess bekannt sind. PostgreSQL unterscheidet SQL-Dumps, Dateisystem-Backups und kontinuierliche Archivierung; jede Methode hat unterschiedliche Stärken und Einschränkungen. Dokumentieren Sie, welche Methode diese Änderung schützt, statt nur allgemein zu erklären, dass ein „Backup abgeschlossen“ wurde.
Ein logischer PostgreSQL-Dump ist ein intern konsistenter Snapshot vom Beginn von pg_dump an, jedoch bilden Vorgänge, die eine exklusive Sperre erfordern, einschließlich der meisten ALTER-TABLE-Varianten, eine Ausnahme von seinem ansonsten nicht blockierenden Verhalten. Bestätigen Sie, dass Zeitpunkt und Methode des Backups mit den Sperr- und Wiederherstellungsanforderungen der Migration vereinbar sind.
Point-in-Time-Recovery ist kein allgemeines Versprechen. Bei PostgreSQL erfordert sie ein geeignetes vorheriges physisches Backup und archivierte Write-Ahead-Logs, die den Zielzeitpunkt abdecken. Fehlen diese Voraussetzungen, führen Sie Point-in-Time-Recovery nicht als verfügbare Option auf.
Airbip bietet konfigurierbare tägliche, wöchentliche und monatliche Backups für Anwendungsbereitstellungen. Teams sollten dennoch Umfang, Aufbewahrungskonfiguration, Datenbankabdeckung und das für ihre eigene Instanz geltende Wiederherstellungsverfahren prüfen, bevor sie sich bei einer Migrationsentscheidung auf diese Backups verlassen.
- Backup-Identität: Methode, Abschlusszeit, Umfang, Speicherort und die Person, die es geprüft hat.
- Vertrauen in die Wiederherstellung: ein kürzlich durchgeführter Wiederherstellungstest, geschätzte Schritte, erforderliche Zugangsdaten, Zielumgebung und bekannte Einschränkungen.
- Migrationsnachweise: genaue Release-Version oder Image-Referenz, Migrationskennungen, Start- und Endzeiten, Logs und Fehler.
- Baseline-Prüfungen: Dokumentieren Sie vor der Änderung wichtige Anzahlen, repräsentative Datensätze, kritische Workflows und den Status von Integrationen.
- Prüfungen nach der Änderung: Dokumentieren Sie dieselben Prüfungen nach der Migration und definieren Sie akzeptable Abweichungen.
- Wiederherstellungsschwelle: Legen Sie vor Beginn die maximal akzeptable Ausfallzeit und das Risiko eines Datenverlusts fest.
Entscheiden Sie, ob ein Wartungsfenster oder eine vorübergehende Schreibbeschränkung erforderlich ist
Ein Wartungsfenster ist gerechtfertigt, wenn die Migration Schreibvorgänge blockieren, inkompatible gemischte Zustände erzeugen, eine unsichere Dauer haben oder eine Wiederherstellung erfordern kann, mit der sich spätere Benutzeränderungen nicht sicher zusammenführen lassen. Eine vorübergehende Schreibbeschränkung kann ausreichen, wenn Lesezugriffe sicher bleiben, Schreibvorgänge aber mit einem Backfill, einer Schemaänderung oder einem möglichen Rollback kollidieren würden.
Richten Sie die Entscheidung an den tatsächlichen Vorgängen und den geschäftlichen Auswirkungen aus. Beispielsweise blockiert ein gewöhnlicher PostgreSQL-Indexaufbau Schreibvorgänge, während ein gleichzeitiger Indexaufbau diese spezifische Schreibsperre vermeidet, aber länger laufende betriebliche Eigenschaften besitzt und keine normale Transaktionsgrenze teilen kann. Keine der beiden Optionen ist automatisch sicherer, ohne Arbeitslast, Timing und Wiederherstellung zu berücksichtigen.
Definieren Sie, was Benutzer sehen und was Operatoren tun werden. Eine Schreibbeschränkung kann bedeuten, Hintergrund-Worker anzuhalten, geplante Importe zu deaktivieren, eine Anwendung in einen vom Hersteller unterstützten Wartungsmodus zu versetzen oder Schreibanfragen vorübergehend abzulehnen. Stellen Sie sicher, dass Integrationen und Administratoren dieselbe Anweisung erhalten; andernfalls könnten sie Daten erzeugen, die die Wiederherstellung erschweren.
- Verwenden Sie ein vollständiges Wartungsfenster, wenn Schemaänderungen oder Wiederherstellungen gleichzeitige Schreibvorgänge unsicher machen.
- Verwenden Sie eine gezielte Schreibbeschränkung, wenn Lesezugriff sicher fortgesetzt werden kann und die Anwendung diesen Modus unterstützt.
- Halten Sie Hintergrund-Worker, Importe, Webhooks und geplante Jobs an oder berücksichtigen Sie sie.
- Legen Sie Startzeit, erwartete Dauer, Entscheidungszeitpunkt für eine Verlängerung und den Kommunikationsweg für Benutzer fest.
- Bestätigen Sie, wie eingereihte Arbeit nach Bereitstellung oder Wiederherstellung fortgesetzt, dedupliziert oder abgeglichen wird.
- Stoppen Sie, wenn Sperren, Dauer oder Fehlerraten den genehmigten Schwellenwert überschreiten.
Wählen Sie den Wiederherstellungspfad vor der Bereitstellung
Wiederherstellung ist ein Entscheidungsbaum, keine einzelne Rollback-Schaltfläche. Genehmigen Sie im Voraus die Bedingungen, unter denen das Team Anwendungscode zurückrollt, Daten wiederherstellt, eine begrenzte Menge von Datensätzen repariert oder mit einer Vorwärtskorrektur fortfährt. Benennen Sie, wer jede Aktion autorisieren kann, insbesondere eine Wiederherstellung, die legitime Schreibvorgänge nach dem gewählten Backup-Zeitpunkt verwerfen könnte.
Ein Code-Rollback ist nur angemessen, wenn die Kompatibilität bestätigt wurde und die Migration keinen für die ältere Version unsicheren Datenbankzustand erzeugt hat. Eine Wiederherstellung ist angemessen, wenn der Datenzustand selbst auf einen bekannten Zeitpunkt zurückkehren muss, erfordert aber einen sorgfältigen Umgang mit Schreibvorgängen nach dem Backup. Eine Datenreparatur kann bei einem kleinen, vollständig verstandenen und prüfbaren Fehler funktionieren. Eine Vorwärtskorrektur ist oft sicherer, wenn durch eine Wiederherstellung mehr gültige Geschäftsvorgänge verloren gingen als durch die Behebung des Fehlers.
Auch das Verhalten des Frameworks ist wichtig. Django kennzeichnet beispielsweise RunPython-Schritte ohne reverse_code und RunSQL-Schritte ohne reverse_sql als irreversibel. Das Transaktionsverhalten von Django-Migrationen variiert zudem je nach Datenbank-Engine: Die Standardbehandlung unterscheidet sich zwischen Engines mit DDL-Transaktionen wie PostgreSQL und SQLite und Engines wie MySQL und Oracle. Lesen Sie die Hinweise zum Migrationsframework der Anwendung und zur jeweiligen Datenbank, bevor Sie annehmen, dass eine Umkehrung verfügbar ist.
- Code-Rollback: Geben Sie die kompatible vorherige Version und die Prüfungen an, die erforderlich sind, bevor der Datenverkehr zurückgeleitet wird.
- Wiederherstellung: Geben Sie Wiederherstellungspunkt, Methode, erwartete Ausfallzeit, Auswirkungen eines Datenverlusts und die verantwortliche Person für den Abgleich an.
- Datenreparatur: Geben Sie die betroffenen Datensätze, das Reparaturskript, den Prüfpfad, die Validierungsabfrage und die Umkehrmethode für die Reparatur selbst an.
- Vorwärtskorrektur: Geben Sie den sicheren Zwischenzustand, die verantwortliche Person, den Eskalationsweg und Maßnahmen zur Begrenzung der Benutzerauswirkungen an.
- Befugnis: Benennen Sie für jede Wiederherstellungsoption den technischen Operator, den geschäftlichen Datenverantwortlichen und den finalen Entscheider.
- Kommunikation: Bereiten Sie interne und benutzerorientierte Nachrichten für verlängerte Wartung, Datenabgleich oder Wiederherstellung des Dienstes vor.
Häufige Fragen
Kann ich eine Datenbankmigration zurückrollen, indem ich den Anwendungscontainer zurückrolle?
Nicht unbedingt. Die Rückkehr zu einem älteren Anwendungs-Image ändert den Code, nicht jedoch das festgeschriebene Datenbankschema oder die Daten. Nutzen Sie einen Code-Rollback erst, nachdem Sie bestätigt haben, dass die ältere Version mit dem Datenbankzustand nach der Migration kompatibel ist.
Was sollte eine Checkliste zum Zurückrollen von Datenbankmigrationen enthalten?
Sie sollte die genauen Schema- und Datenänderungen, die Reversibilität der Migration, die Kompatibilität von altem und neuem Code, Sperr- und Ausfallrisiken, Backup-Methode und -Umfang, Nachweise aus Wiederherstellungstests, Validierung vor und nach der Änderung, einen Plan zur Steuerung von Schreibvorgängen, Wiederherstellungsoptionen und benannte Entscheider enthalten.
Wann reicht ein Backup für ein sicheres Rollback nicht aus?
Ein Backup allein reicht nicht aus, wenn das Team nicht weiß, ob es die Datenbank einschließt, ob es wiederhergestellt werden kann, welchen Zeitpunkt es abbildet oder wie mit Benutzeränderungen nach dem Backup umgegangen wird. Ein Wiederherstellungsplan benötigt sowohl Nachweise als auch eine geschäftliche Entscheidung über akzeptablen Datenverlust.
Ist CREATE INDEX CONCURRENTLY in PostgreSQL immer die richtige Option?
Nein. Es vermeidet das Blockieren paralleler Inserts, Updates und Deletes, kann jedoch nicht innerhalb eines Transaktionsblocks ausgeführt werden, verwendet zusätzliche Tabellenscans und wartet auf relevante Transaktionen. Wählen Sie es anhand von Arbeitslast, Bereitstellungstooling, Dauer und Fehlerbehandlung.
Wann sollten wir für eine Datenbankmigration ein Wartungsfenster verwenden?
Verwenden Sie eines, wenn Vorgänge Schreibvorgänge blockieren können, alte und neue Anwendungsversionen nicht sicher gleichzeitig bestehen können, Hintergrundaktivität die Wiederherstellung erschweren würde oder eine Wiederherstellung die wahrscheinliche Reaktion auf einen Fehler wäre. Bei Änderungen mit geringeren Auswirkungen kann eine vorübergehende Schreibbeschränkung ausreichen, wenn Lesezugriffe sicher fortgesetzt werden können.
Wie passt Airbip zur Bereitschaft für Datenbankmigrationen?
Airbip verwaltet Docker-basierte Anwendungsbereitstellungen und bietet konfigurierbare tägliche, wöchentliche und monatliche Backups. Die Migrationsbereitschaft bleibt eine gemeinsame betriebliche Verantwortung: Das Team muss prüfen, was gesichert wird, gegebenenfalls Wiederherstellungen testen, das Migrationsverhalten der Anwendung verstehen sowie Daten- und Wiederherstellungsentscheidungen freigeben.
Quellen und weiterführende Literatur
- PostgreSQL transactions — PostgreSQL Global Development Group
- PostgreSQL ALTER TABLE — PostgreSQL Global Development Group
- PostgreSQL CREATE INDEX — PostgreSQL Global Development Group
- PostgreSQL backup and restore — PostgreSQL Global Development Group
- PostgreSQL SQL dump — PostgreSQL Global Development Group
- PostgreSQL write-ahead logging — PostgreSQL Global Development Group
- PostgreSQL MVCC caveats — PostgreSQL Global Development Group
- Django migration operations — Django Software Foundation
- Django migrations — Django Software Foundation
- Docker Compose volume reference — Docker