Die meisten der gruseligsten Einsätze, die mir einfallen, hatten eines gemeinsam: eine Datenbankänderung. Der Code war in Ordnung. Sie können den Code in Sekunden zurückführen. Aber wenn man eine Spalte fallen gelassen hat, eine Tabelle umbenannt hat oder eine Million Zeilen migriert hat, gibt es keine schnelle Unwenden.
Datenbankänderungen müssen ihren eigenen Platz in Ihrem Lieferprozess haben. Hier ist, wie man sie routinemäßig macht.
Warum Migrationen Dinge zerstören
Ein paar klassische Möglichkeiten, wie Schemaänderungen Ausfälle verursachen:
- Der neue Code erwartet eine Spalte, die noch nicht existiert, weil die Migration nach dem Einsatz ausgeführt wurde oder fehlgeschlagen ist.
- Der alte Code bricht auf dem neuen Schema, da bei einem laufenden Update beide Versionen gleichzeitig ausgeführt werden.
- Ein Rückzug des Codes lässt die Datenbank in der neuen Form, und der alte Code versteht es nicht.
- Eine lange Migration schließt einen Tisch einUnd alles, was darauf wartet, ist aus.
- Jemand hat die Datenbank von Hand verändert., und die Migration scheitert, weil die Realität nicht den Erwartungen entspricht.
Das gemeinsame Thema: Code und Datenbank ändern sich zu verschiedenen Zeiten, und für eine Weile sprechen sowohl alte als auch neue Versionen des Codes mit derselben Datenbank.
Erweitern, dann schrumpfen
Das nützlichste Muster für sichere Datenbankmeldungen ist Ausweitung und Verringerung (auch Paralleländerung genannt). Statt einer einzigen, sich brechenden Änderung, machen Sie eine Reihe kompatibler.
Beispiel: Umbenennung einer Spalte von name zu full_name.
- Ausweiten: die neue Spalte hinzufügen
full_name- Ich weiß . Der alte Code ignoriert es.
- Schreiben Sie an beide: Code bereitstellen, der auf beide schreibt
name und full_name, und liest von name.
- Rückfüllung: Kopieren bestehender Daten aus
name zu full_name, in Chargen.
- Schalter wird gelesen: Code bereitstellen, der von
full_name.
- Hör auf mit der alten Kolumne.: Code bereitstellen, der nur
full_name.
- VertragSie können sich später, wenn Sie sich sicher sind, die
name Kolonne.
Mehr Schritte, sicher. Aber in jeder Phase funktionieren sowohl die aktuelle als auch die vorherige Codeversion, so dass jede Bereitstellung sicher rückgängig gemacht werden kann.
Machen Sie niemals Änderungen an einer Datenbank, die die vorherige Version Ihres Codes nicht überstehen kann.
Dazu gibt es keine Regeln.
- Zusatzveränderungen sind sicher: neue Tabellen, neue nullfähige Spalten, neue Indizes (gleichzeitig erstellt, wenn Ihre Datenbank diese unterstützt).
- Schädliche Veränderungen brauchen eine Wartezeit: das Ablegen oder Umbenennen von Spalten und Tabellen erst, wenn kein laufender Code sie verwendet.
- Vermeiden Sie lange Schlösser: große Datenmigrationen in Chargen, nicht eine riesige Transaktion. Wissen, welche Operationen die Tabellen in Ihrer Datenbank sperren.
- Abgesonderte Schemaänderungen bei Datenmigrationen wenn möglich.
- Die Migrationen sind nur in der Produktion vorwärts. "Abwärts" Migrationen sind nützlich in der Entwicklung, aber in der Produktion, setzen Sie mit einer neuen Migration voran.
Werkzeuge: Atlas, Flugbahn, Liquibase
Sie brauchen ein Tool, das Migrationen in der Reihenfolge anwendet und aufzeichnet, was angewendet wurde:
- Flugbahn: einfach, SQL-Datei-basiert, weit verbreitet, vor allem in der Java-Welt.
- Flüssigkeitsbasis: ChangeSets in SQL, XML, YAML oder JSON mit vielfältigen Funktionen für Unternehmen.
- Atlas: ein neueres Instrument mit einem deklarativen Ansatz. Sie beschreiben das gewünschte Schema, und Atlas plant die Migration, wie Terraform für Datenbanken. Es wird auch für gefährliche Änderungen geprüft, wie zum Beispiel das Ablegen einer Spalte oder das Hinzufügen einer nicht nullfähigen Spalte ohne Standard.
- Rahmenwerkzeuge: Django-Migrationen, Rails-Migrations, Alembic, Prisma, EF Core. Es ist gut, wenn Ihre App-Framework hat sie zu verwenden.
Wann Migrationen durchgeführt werden sollen
Häufige Optionen in einer Kubernetes-Welt:
- Ein Kubernetes-Job vor der Bereitstellung, zum Beispiel ein Helm-Vor-Upgrade-Haken oder ein Argo CD-Sync-Welle / Vor-Synchronisierungs-Haken. Die Bereitstellung wird nur fortgesetzt, wenn die Migration erfolgreich ist.
- Ein Initial-Container in der App-Pod. Einfach, aber bei vielen Repliken können mehrere versuchen, gleichzeitig zu migrieren. Verwenden Sie ein Werkzeug mit Schließung.
- Ein separater Pipeline-Schritt vor der Bereitstellung der neuen Version.
Egal, was Sie wählen, die Migration muss erfolgreich sein. vorher Der neue Code braucht ihn und darf den alten Code nicht brechen, der noch läuft.
Tests von Migrationen in der Gemeinschaft
- Alle Migrationen von Grund auf neu starten Auf einer neuen Datenbank in CI, um sicherzustellen, dass die Kette funktioniert.
- Führen Sie neue Migrationen gegen eine Kopie von produktionsähnlichen Daten durch (anonymisiert) um Leistungsprobleme und Schlösser zu erkennen.
- Lintwanderungen für riskante Operationen (Atlas, squawk für PostgreSQL und ähnliche Tools).
- Beide Codeversionen testen gegen das neue Schema, wenn Sie können.
Wie macht man Datenbankänderungen langweilig?
Verwenden Sie ein Migrationswerkzeug, machen Sie jede Änderung rückwärts kompatibel mit expand and contract, führen Sie Migrationen automatisch durch, bevor der Code sie benötigt, und testen Sie sie in CI mit realistischen Daten. Es sind mehr Schritte, aber jeder Schritt ist klein und sicher.
Meine Meinung: Datenbanken haben ein langes Gedächtnis. Ändern Sie sie langsam, in kleinen, kompatiblen Schritten, und sie werden Ihnen vergeben.
Desly