Eine Datenbankmigration kann zweimal ausgeführt werden, wenn mehr als ein Startpfad, Container oder Scheduler glaubt, für denselben Aktualisierungsschritt zuständig zu sein.
Selbst gehostete Anwendungen starten Migrationen häufig über einen Entrypoint, Webprozess, Worker, Sidecar, eine systemd-Unit oder einen Deployment-Hook. Nach einer erneuten Bereitstellung kann ein alter Container einen neuen überlappen, eine Neustartrichtlinie kann einen fehlgeschlagenen Migrationsprozess erneut starten oder zwei Replikate können die Datenbank erreichen, bevor eines davon den Abschluss registriert. Die Diagnose sollte jeden potenziellen Ausführer ermitteln und nachweisen, ob das Migrationsframework eine dauerhafte Sperre oder einen Schema-Verlaufsdatensatz verwendet, bevor eine Datenreparatur beginnt.
Jeden Prozess ermitteln, der die Migration starten kann
Durchsuche den Entrypoint des Images, den Compose-Befehl, den Worker-Befehl, die systemd-Unit, den Cronjob, das Deployment-Skript und das Anwendungsstartprotokoll nach dem Migrationsbefehl. Erfasse Prozess-IDs und Containernamen zu den beiden Ausführungszeitpunkten.
Docker Compose kann Dienste gemäß den deklarierten Abhängigkeiten starten, aber die Startreihenfolge allein macht eine Migration auf Anwendungsebene nicht zu einer Aufgabe mit nur einem Verantwortlichen. Die offizielle Anleitung zur Startreihenfolge zeigt, warum die Verfügbarkeit einer Datenbank und die eindeutige Zuständigkeit für eine Migration getrennte Bedingungen sind.
Wenn derselbe Befehl sowohl im Web-Entrypoint als auch in einem dedizierten Migrationsdienst erscheint, entferne eine der beiden Zuständigkeiten. Wenn nur ein Befehl existiert, prüfe als Nächstes Replikate, Neustartschleifen und Datensätze zum Migrationsstatus.
Überlappende alte und neue Container prüfen
Liste während der Bereitstellung laufende, neu startende, beendete und verwaiste Container auf. Vergleiche Projektnamen, Dienstnamen, Container-IDs und Erstellungszeitpunkte.
Systemd dokumentiert, dass eine Dienst-Neustartrichtlinie einen fehlgeschlagenen Befehl entsprechend den Einstellungen der Unit erneut starten kann. Das Neustartmodell für Dienste hilft zu erklären, warum ein Host-Starter die Migration erneut ausführen kann, nachdem der containerisierte Versuch mit einem Fehlercode beendet wurde.
Entferne nachweislich verwaiste Ausführer erst, nachdem du ihre Protokolle gesichert hast. Ein zweiter Migrationszeitstempel kurz nach dem ersten weist häufig auf einen Wiederholungsversuch und nicht auf einen separat geplanten Job hin.
Vor Schemaänderungen eine Datenbanksperre verwenden
Ermittle, ob die Anwendung eine Sperre auf Datenbankebene erwirbt, bevor sie den Migrationsstatus liest und Änderungen anwendet. Teste zwei gleichzeitige Startversuche in einer Wegwerfumgebung.
PostgreSQL stellt Advisory Locks zur anwendungsdefinierten Koordination bereit. Damit kann ein Migrationsausführer einen anderen ausschließen, selbst wenn beide nahezu gleichzeitig starten.
Eine Sperre muss das gesamte Entscheidungs- und Ausführungsfenster abdecken. Wenn die aktuelle Schemaversion vor dem Erwerb der Sperre geprüft wird, können weiterhin zwei Ausführer dieselbe ausstehende Migration auswählen.
Sperrsemantik bei MySQL oder MariaDB prüfen
Prüfe bei MySQL-kompatiblen Anwendungen, ob das Migrationstool eine benannte Sperre, eine Transaktion oder eine Sperrtabelle verwendet und ob die Verbindung während der gesamten Migration bestehen bleibt.
MySQL dokumentiert verbindungsgebundene benannte Sperren. Diese werden freigegeben, sobald die zugehörige Sitzung endet, und müssen daher nach einem Absturz oder Neustart sicher erneut erworben werden.
Eine fehlgeschlagene Verbindung kann die Sperre freigeben, bevor das Migrationsframework den Abschluss registriert. Vergleiche die Datenbankprotokolle mit den Zeitstempeln der Containerneustarts, um diese Abfolge zu erkennen.
Die Verlaufstabelle des Migrationsframeworks prüfen
Liste Migrationskennungen, Ausführungsreihenfolge, Erfolgskennzeichen, Prüfsummen und Zeitstempel auf. Vergleiche die beiden protokollierten Ausführungen mit den Datensätzen, die tatsächlich in der Datenbank festgeschrieben wurden.
Flyway verwendet eine Schema-Verlaufstabelle, um angewendete Migrationen und ihren Status zu verfolgen.
Wenn der erste Lauf das Schema geändert hat, aber vor der Erfolgsaufzeichnung fehlgeschlagen ist, versucht der zweite Lauf möglicherweise eine Migration erneut, die nicht idempotent geschrieben wurde. Repariere den Verlauf erst, nachdem du das tatsächliche Schema mit dem erwarteten Ergebnis der Migration verglichen hast.
Identität und Prüfsummen der Änderungsprotokolle prüfen
Vergleiche vor und nach der Image-Aktualisierung Migrationsdateinamen, IDs, Autoren, Pfade und Prüfsummen. Ermittle, ob das Image doppelte oder umbenannte Einträge im Änderungsprotokoll enthält.
Liquibase erfasst ausgeführte Änderungen in der Tabelle DATABASECHANGELOG. Die Identität einer Änderung basiert dort auf ihrer ID, ihrem Autor und ihrem Dateipfad.
Das Verschieben einer Änderungsprotokolldatei oder das erneute Generieren von Kennungen kann alte Arbeit als neu erscheinen lassen, selbst wenn das SQL ähnlich ist. Stelle eine stabile Migrationsidentität wieder her, anstatt große Verlaufsbereiche manuell zu löschen.
Mit nur einem Migrationsverantwortlichen erneut bereitstellen und Idempotenz prüfen
Bestimme einen einzigen Migrationsverantwortlichen, füge eine dauerhafte Sperre hinzu, lasse Web- und Worker-Dienste auf den erfolgreichen Abschluss warten und stelle die Anwendung in einer Testkopie der Datenbank erneut bereit.
Der ZimaSpace-Artikel zu Planungsgrenzen von Containern liefert die ergänzende Regel: Eine Wartungsaufgabe sollte genau einen nachgewiesenen Laufzeitverantwortlichen haben.
Das Problem ist behoben, wenn gleichzeitige oder wiederholte Starts genau eine angewendete Migration, einen dauerhaften Verlaufseintrag und nach einem Neustart keine zweite Schemaänderung erzeugen.
Häufig gestellte Fragen
Beschädigt die zweimalige Ausführung einer Migration immer die Datenbank?
Nein. Idempotente Migrationen können vorhandene Objekte sicher erkennen, aber nicht idempotente Datentransformationen, Indexerstellungen oder Spaltenänderungen können fehlschlagen oder Daten duplizieren.
Sollte jedes Web-Replikat Migrationen ausführen dürfen?
Nur wenn das Framework eine zuverlässige Koordination auf Datenbankebene bereitstellt. Ein dedizierter, einmalig ausgeführter Migrationsverantwortlicher lässt sich in einer Home-Server-Bereitstellung leichter überprüfen.
Kann ich die Migration manuell als abgeschlossen markieren?
Nur nachdem nachgewiesen wurde, dass das aktive Schema und die Daten dem erwarteten Ergebnis der Migration entsprechen. Wird der Verlauf zuerst bearbeitet, kann eine teilweise angewendete Änderung verborgen werden.
Support & Tipps
Mehr zum Lesen

Warum stellt eine Docker-Volume-Wiederherstellung zwar die Dateiinhalte wieder her, lässt aber erweiterte Attribute weg?
Eine Diagnose zur Wiederherstellung von Volumes mit einer Bestandsaufnahme der erweiterten Attribute, Tar- und Rsync-Optionen, Namespaces, Zielunterstützung, Berechtigungen, Labels, App-Metadaten und Tests.

Warum behält ein laufender Container sein altes Speicherlimit bei, nachdem die Compose-Datei geändert wurde?
Eine Diagnose der Speicherbegrenzung mit Erläuterungen zu aktiven cgroups, Neustart gegenüber Neuerstellung, Compose-Feldern, harten und weichen Limits, übergeordneten Bereichen, Swap sowie Laufzeit-Heaps.

Warum macht ein Neustart des Reverse-Proxys jede Sitzung für eine selbst gehostete App ungültig?
Eine Diagnose von Sitzungsverlusten mit Abdeckung des Neustartumfangs, der Cookie-Zuständigkeit, der Geheimnisrotation, cachebasierten Sitzungen, Sticky-Routing, Authentifizierungs-Gateways und der Wiederherstellung.

