Bei der Konzeption einer SaaS sollten folgende Themen frühzeitig und umfassend konzeptuell betrachtet und gelöst werden, die ich als Teil von “Database Operations” betrachten würde:

  • Environment Specific Database Schema Migrations (DDL, DML)
  • Environment Specific Data Initialization (DML)
    • Basic Data
    • Test Data
Database-OperationBeschreibung
DDL Schema-Migrations– Datenbank Schema Änderungen
– Tabellen Anlegen / Löschen
– Tabellen Spalten Anlegen / Löschen
– Index, Schlüssen Anlegen / Löschen
– …

– werden in GIT eingecheckt
– werden durch ein Tool (Liquibase, Flyway) automatisiert ausgeführt.
– fangen an zu “verwahrlosen”, sobald es zu viele werden.
– sollten bei zu großer Menge und Komplexität wieder über das frische Erzeugen eines Prod-Schemas neu aufgesetzt werden
– nach dieser Zeit können ältere Stände nicht mehr mit einem Rollback zurückgesetzt werden.
DML Schema-Migrations– Insert/Update/Delete Statements
– Einfügen von Basisdaten (Language-Tabelle, Enum-Typ-Tabellen, …).
– Befüllen/Vorbereiten von statischen Werten die mandantenübegreifend identisch sind und sich nicht über UI ändern lassen.
– Sind abhängig von den zugehörigen DDL und müssen entsprechend in ihrer Ausführungsreihenfolge eingetaktet werden.

– werden in GIT eingecheckt
– werden durch ein Tool (Liquibase, Flyway) automatisiert ausgeführt.
– fangen an zu “verwahrlosen”, sobald es zu viele werden.
– sollten bei zu großer Menge und Komplexität gelöscht werden und wieder bei 0 begonnen werden (da ein Zusammentragen aller Basisdaten aus der Prod-Datenbank realistisch gesehen zu aufwendig wäre).
– nach dieser Zeit können ältere Stände nicht mehr mit einem Rollback zurückgesetzt werden.
Data Initializations– Insert/Update/Delete Statements
– Einfügen von Basisdaten (Language-Tabelle, Enum-Typ-Tabellen, …).
– Befüllen/Vorbereiten von statischen Werten die mandantenübegreifend identisch sind und sich nicht über UI ändern lassen.
– Sind immer nur vom neusten/atuellen Stand der DDL abhängig da es keine Möglichkeit für einen Rollback gibt.

– werden in GIT eingecheckt
– werden in Code (Java, Python) geschrieben und durch eigene Implementierungen zu einem passenden Zeitpunkt (nach Ausführung der DDL, vor Ausführung der IT/Unit-Tests) ausgeführt.
– sind sauber gepflegt und sehr übersichtlich (Bestandsaufnahme)
– sind zu unterscheiden in Basisdaten und Testdaten und es muss möglich sein individuell nur eines davon anzuwenden.

Es macht Sinn von folgenden Environments unserer SaaS auszugehen:

  • local
  • dev
  • staging
  • prod
  • IT/Unit-Test Ausführung

Diese Environments haben unterschiedliche Anforderungen an die obig beschriebenen Database Operations, die ich im folgenden aufführe:

EnvironmentsAnforderungen
local, dev, staging, prodRegelmässige Migration:

– DDL und DML SQL-Changesets müssen in einer festgelegten Reihenfolgen automatisiert angewendet werden können um auf ein neues Schema und neue Daten migrieren zu können, ohne dass die eigene Arbeit unterbrochen werden muss.

– DDL und DML SQL-Changesets müssen über manuelle Rollbacks bei Bedarf zurückgenommen werden können, um die Zieldatenbank in einen älteren Stand versetzen zu können (beispielsweise bei Branch-Wechsel in der lokalen Entwicklung)
– In dev, staging, prod sollten jedoch keine Rollbacks durchgeführt werden.


Erstintialisierung:

– Bei einer Erstinitialisierung eines Environments ist die Ausführung aller DML SQL-Changesets oft nicht wünschenswert, da sich eine hohe Menge an Changesets über die Zeit ansammelt. Dies ist einerseits langsam und es kann passieren dass DML SQL-Changesets beim Deploy selbst fehlerhaft waren und später manuell in der Datenbankinstanz nachkorrigiert werden mussten. In diesem Fall kann man sich nicht auf die vollständige Sauberkeit des DML SQL-Changeset Trace im Git verlassen und er kann daher auch nicht für die Erstinitialisierung eines Environments genutzt werden. Auch DDL-Statements sind vor Problemen nicht gefeit, wenn Index oder Fremdschlüsselbeziehungen bei der Anlege aufgrund ungünstiger Datenstände Probleme machen (diese müssen wie oben beschrieben daher in unregelmässigen Abständen aus einem frischen Prod-Schema neu erzeugt werden).

– Da sich in den Environments selbst die Daten auch stark verändern, können wir bei den DDL an sich auch nicht von einem vollständigen Trail ausgehen. Es wird immer wieder Zeitpunkte geben, wo man seine DML und DDL Dateien frisch aus einem vorhandenen Prod/Staging-Schema neu aufsetzt um wieder sauber starten zu können, weil sich über die Zeit sonst zu viele Changeset-Dateien ansammeln. Sobald dies passiert, sind dann auch DDL Dateien nicht mehr als vollständig für das Aufsetzen einer frischen Datenbankinstanz zu betrachten, da sie lediglich die aktuell nötigen Änderungen für frische Features umfassen.

Aufgrund dieser Punkte wird folgende Möglichkeit für die Erstintialisierung eines Environment empfohlen:
– 1. nur DDL SQL-Changesets anwenden, jedoch auch die DML SQL-Changesets als angewandt markieren (diese jedoch nicht anwenden).
– 2. Basic Data-Initialization ausführen (DataInit)
– 3. Danach wie oben bei der regelmässigen Migration fortfahren.
IT/Unit-Test AusführungBeim Schreiben von IT/Unit-Tests ist es wichtig, sowohl die Basisdaten als auch die grundlegend verfügbaren Testdaten auf einen Blick erkennen zu können. Wenn diese jedoch über viele DML SQL-Changesets verstreut sind, wird es schwer beim Schreiben der Tests den Überblick zu bewahren.

Für die Ausführung der IT/Unit-Tests ist es sinnvoll einen Testcontainer (Mariadb, Postgresql) bereitzustellen, der nur für diese Ausführung frisch aufgesetzt wird und nach der Ausführung wieder gelöscht wird.

Dieser frische Testcontainer wird dann wie folgt bestückt:
– 1. Nur DDL SQL-Changesets anwenden
– 2. Basic Data-Initialization ausführen (DataInit)
– 3. Test Data-Initialization ausführen (DataInit)

Danach können die IT/Unit-Tests ausgeführt werden.

Wir können uns hier nun Liquibase, Testcontainers und ein eigenes kleines Framework für DataInit aufbauen, um all diese Punkte in einem Backend-Projekt umsetzen zu können.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert