Es wurden viele Artikel darüber geschrieben, wie Systeme im laufenden Betrieb aktualisiert werden können, ohne sie zu stoppen (Bereitstellung ohne Ausfallzeiten), und viele Aspekte dieses Ansatzes sind ziemlich offensichtlich. Meiner Meinung nach ist der schwierigste Teil der Bereitstellung in diesem Fall die Aktualisierung von Data Warehouses, wenn sich ihr Vertrag (Schema) geändert hat. Diesen Aspekt möchte ich in diesem Artikel berücksichtigen.
Unabhängig von der Datenbank - mit einem expliziten Datenschema als relational oder mit einem beliebigen als NoSQL - ist das Datenschema auch auf Anwendungsebene noch vorhanden. Die aus der Datenbank gelesenen Daten sollten für den Client verständlich sein, auch wenn das Repository selbst keine Einschränkungen für seine Struktur auferlegt.
Angenommen, ein System mit einer bestimmten Datenstruktur und Terabyte an Daten in der Datenbank wird bereits in der Produktion ausgeführt. In der neuen Version des Systems müssen wir die Struktur geringfügig ändern, um neue Funktionen zu implementieren oder die Leistung zu verbessern. Überlegen Sie, welche Änderungen in der Schaltung auftreten können:
- Hinzufügen eines neuen Feldes
- Feld löschen
- Feld umbenennen
- Feldtypänderungen
- Übertragen eines Feldes in eine andere Datenstruktur (z. B. bei Denormalisierung)
Das Hinzufügen eines neuen Felds sowie das Hinzufügen eines anderen Datenbankobjekts ist eine abwärtskompatible Änderung und erfordert keine zusätzlichen Schritte zur Implementierung einer Bereitstellung ohne Ausfallzeiten (mit einer Einschränkung - wenn dieses neue Feld oder Objekt nicht funktional von anderen bereits in der Datenbank gespeicherten Feldern abhängt Daten). Wenden Sie die Änderungen einfach im laufenden Betrieb auf die Datenbank an und stellen Sie dann eine neue Version des Codes bereit, der die neuen Datenbankobjekte verwendet.
Das Löschen eines Felds oder eines anderen Datenbankobjekts ist keine abwärtskompatible Änderung, aber die Vorgehensweise bei der Implementierung ist sehr einfach. Unnötige Datenbankobjekte sollten erst gelöscht werden, nachdem die neue Version des Systems vollständig blockiert ist.
Die anderen drei Arten von Änderungen sind komplexer, da sie eine Bereitstellung ohne Ausfallzeiten ermöglichen. Im Allgemeinen können alle ausgeführt werden, indem Daten in andere Felder / Entitäten kopiert und die „alten“ nach erfolgreicher Datenmigration gelöscht werden: Zum Umbenennen können Sie Daten aus dem alten Feld in ein Feld mit einem neuen Namen kopieren, dann das alte Feld löschen und den Datentyp ändern kann zusammen mit dem Umbenennen usw. durchgeführt werden. Auf die eine oder andere Weise muss die Datenbank über einen bestimmten Zeitraum sowohl alte als auch neue Verträge unterstützen. Es gibt mindestens zwei Möglichkeiten, solche Änderungen im laufenden Betrieb vorzunehmen:
Wenn die Datenbank Trigger unterstützt
- Erstellen Sie Trigger, die bei jeder Änderung / Hinzufügung Daten vom alten zum neuen Ort kopieren und in der Produktion festlegen.
- Wenden Sie ein Datenkonvertierungsprogramm an, das dasselbe tut, jedoch für alle Datensätze in der Datenbank. Da die Trigger bereits installiert sind, führt das Dienstprogramm möglicherweise nichts Komplizierteres aus als nur eine „fiktive“ Aktualisierung jedes Datensatzes (UPDATE-Tabelle SET field = field ...). Ein sehr wichtiger Punkt hierbei ist, dass das Lesen von Daten vom alten Ort und das Schreiben auf den neuen atomar sein und vor verlorenen Änderungen geschützt werden sollte. Abhängig von der Struktur der Datenbank können Sie entweder die pessimistische Sperre über SELECT FOR UPDATE oder seine Analoga verwenden oder optimistisch, wenn die Tabelle ein Feld mit einer Datensatzversion enthält.
- Nachdem das Dienstprogramm seine Arbeit beendet hat (abhängig von der Datenmenge und der Komplexität des Updates kann die Ausführungszeit Tage dauern), ist es bereits möglich, eine neue Version des Systems zu installieren, die das neue Datenschema unterstützt. Zu diesem Zeitpunkt werden alle Datensätze in der Datenbank, die zum Zeitpunkt des Starts des Dienstprogramms vorhanden waren, erfolgreich konvertiert, und alle neuen Datensätze, die während des Betriebs angezeigt wurden, werden ebenfalls durch Trigger konvertiert.
- Löschen Sie Trigger und alle Felder (oder andere Datenbankobjekte), die nicht mehr benötigt werden.
Wenn es nicht möglich ist, Trigger zu verwenden (wie es bei vielen NoSQL-Lösungen der Fall ist)

- Erstellen Sie eine neue Version der Anwendung und stellen Sie sie bereit (temporäre Version 1 in der Abbildung), die immer aus dem alten Feld liest. Beim Schreiben in dieses Feld werden jedoch sowohl die alte als auch die entsprechende neue Stelle aktualisiert (in der Abbildung „C“ - die alte, „H“ -). neu). Zadeplit diese Version auf alle Knoten, auf denen die Anwendungsinstanzen ausgeführt werden.
- Wenden Sie ein Dienstprogramm an, das Daten vom alten zum neuen Speicherort kopiert. Wie bei Triggern müssen Sie Maßnahmen ergreifen, um verlorene Änderungen zu vermeiden.
- Erstellen und installieren Sie nach Abschluss des Dienstprogramms eine andere Version der Anwendung (temporäre Version 2), die Daten aus einem neuen Feld liest, aber dennoch an zwei Stellen schreibt. Dieser Schritt ist erforderlich, da während der sequentiellen Aktualisierung jedes Knotens immer noch eine Lücke besteht, wenn die Instanzen der vorherigen Version der Anwendung, die das alte Feld liest, gleichzeitig mit dem neuen arbeiten.
- Erstellen Sie und stellen Sie am Ende des vollständigen Durchlaufs des vorherigen die endgültige Version bereit, die bereits nicht mit dem alten Feld interagiert.
- Alte Felder löschen.
Der zweite Ansatz erfordert die Erstellung und Installation von drei verschiedenen Versionen der Anwendung, was sehr unpraktisch und umständlich sein kann. Stattdessen können Sie das Umschalten von Funktionen verwenden, um die Logik aller drei Versionen in eine zu integrieren. Wechseln Sie jedoch den Modus in Abhängigkeit von den Konfigurationsparametern, die idealerweise im laufenden Betrieb umgeschaltet werden können. Anstatt jede nachfolgende Version zu installieren, reicht es daher aus, den Wert des Parameters zu ändern (und den Dienst neu zu starten, wenn die Konfiguration nicht sofort aktualisiert wird). Nach erfolgreichem Abschluss der Installation der endgültigen Version sollte der gesamte Code zur Sicherstellung der Datenmigration vollständig aus dem Arbeitszweig entfernt werden, auch wenn er bis zum nächsten Systemupdate in der Produktion "aktiv" ist.
Es ist leicht zu bemerken, dass die Sicherstellung einer Ausfallzeit von null beim Aktualisieren des Systems ein umständliches und fragiles Verfahren ist. Daher ist es sinnvoll, sich nur dann damit zu befassen, wenn eine entsprechende Anforderung des Unternehmens vorliegt. Aber selbst wenn die Anforderungen an die Systemverfügbarkeit recht niedrig sind (z. B. 99% pro Jahr und das Fenster für das geplante Systemupdate 24 Stunden), kann die für die Installation der neuen Version erforderliche Datenkonvertierung noch länger dauern. Daher müssen Sie im Voraus auf die Verwendung solcher Lösungen vorbereitet sein, wenn Sie große Datenmengen speichern möchten.
Ein alternativer Ansatz kann die absichtliche Ablehnung von rückwärts inkompatiblen Änderungen im Datenbankschema sein. In der Praxis ist dies jedoch leider nicht immer möglich, da die Umstrukturierung des Schemas häufig die effektivste Methode zur Verbesserung der Datenzugriffsleistung ist.