Zum Inhalt
wannacode

Schema-Migrationen

Kurz gesagt: Eine Schema-Migration ist eine nummerierte Änderung am Schema der Datenbank, die einmal läuft und die Datenbank auf jedem Rechner auf derselben Version hält.

Problem

„no such column: phone“

Ein Kollege legt auf seinem Computer eine Spalte phone in customers an und schreibt den Code, der sie anzeigt. Auf seinem Computer funktioniert alles. Die neue Version geht auf die Seite, und die Seite „Kunden“ scheitert mit no such column: phone, weil die Datenbank der Seite diese Spalte nicht hat. Und ein dritter Computer im Team hat zwei Spalten, weil dort jemand sie von Hand unter einem anderen Namen angelegt hat.

Der Code ist in git, und alle haben dieselbe Version. Das Schema der Datenbank braucht dasselbe: aufgeschrieben, versioniert und überall gleich.

Die Idee

Eine Migration: eine nummerierte Änderung

Eine Migration ist eine kleine SQL-Datei mit einer Nummer. Jede Änderung am Schema ist eine neue Datei, und die Dateien liegen in git neben dem Code:

migrations/
001_create_shop.sql
002_reviews.sql
003_customers_phone.sql

Die Datenbank merkt sich in einer Tabelle, welche gelaufen sind, meist schema_migrations. Beim Start (oder wenn eine neue Version ausgeliefert wird) führt das Werkzeug der Reihe nach nur die Dateien aus, die noch nicht darin stehen. Diese Datenbank ist auf Version 2:

SQLDatenbank: Shop

Migration 3 ist die Änderung plus ihr Eintrag, zusammen in einer Transaktion:

SQLDatenbank: Shop

Führ sie ein zweites Mal im selben Feld aus, und ALTER TABLE bleibt mit „duplicate column name“ stehen. Deshalb prüft das Werkzeug schema_migrations, bevor es eine Datei ausführt.

Sieh es dir an

Warum in einer Transaktion

Wenn eine Migration ohne Transaktion auf halbem Weg stehen bleibt, bleibt die erste Änderung, und der Eintrag der Version fehlt. Der nächste Versuch beginnt wieder von vorn und stolpert über seinen eigenen ersten Schritt. Hier ist die zweite Anweisung ein Fehler (dieselbe Spalte zweimal):

SQLDatenbank: Shop

Die Transaktion bleibt mit dem ersten ALTER TABLE offen, und das COMMIT erreicht die Datenbank nie. Führ im Feld ROLLBACK; aus, und die Spalte phone verschwindet: In SQLite und PostgreSQL gehört eine Schemaänderung zur Transaktion. Du korrigierst die Datei und führst sie noch einmal aus, und die Datenbank ist genau so, wie sie war.

Probier es aus

Migration 3: Treuepunkte

Schreib Migration 3 für die Datenbank auf Version 2: eine Spalte loyalty_points in customers (eine ganze Zahl, Pflichtfeld, standardmäßig 0) und den Eintrag (3, 'loyalty_points', '2026-10-25') in schema_migrations, in einer Transaktion.

SQLDatenbank: Shop

Die Idee

Die Werkzeuge

Niemand schreibt die Prüfung „welche Migration ist gelaufen“ von Hand. Jede Sprache hat ein Werkzeug, das die Versionstabelle führt und die Dateien der Reihe nach ausführt:

  • Java: Flyway oder Liquibase (V3__customers_phone.sql);
  • C#: EF Core Migrations (dotnet ef migrations add CustomersPhone) schreibt die Migration aus der Änderung in den Klassen;
  • Python: Alembic (für SQLAlchemy) oder Django-Migrationen;
  • JavaScript: Prisma Migrate, Knex oder node-pg-migrate.

Manche schreiben auch einen Rückwärtsschritt (down), der die Migration rückgängig macht. Auf einer Seite mit echten Daten ist der Weg zurück selten ein DROP COLUMN: Wenn die neue Spalte schon Daten enthält, verliert der Rückwärtsschritt sie. „Zurück“ ist deshalb meist eine neue Migration nach vorn.

Sieh es dir an

Eine laufende Datenbank ändern: in Schritten

Die Seite steht nicht still, während die neue Version ausgeliefert wird: Eine Weile laufen der alte und der neue Code nebeneinander. Wenn die Migration city in town umbenennt, scheitert der alte Code in derselben Sekunde. Deshalb geschieht die Änderung in drei Schritten:

  1. Erweitern. town hinzufügen und aus city füllen. Der alte Code merkt nichts davon.
  2. Umstellen. Der neue Code schreibt in beide und liest town. Du wartest, bis der alte Code überall weg ist.
  3. Zurückbauen. Eine eigene, spätere Migration entfernt city.
SQLDatenbank: Shop

Übung

Vor- und Nachname getrennt

Der Shop will Kunden mit dem Vornamen begrüßen („Hallo, Maria“). Mach den ersten Schritt (Erweitern): Füge die Spalten first_name und last_name zu customers hinzu und fülle sie aus name (jeder Name besteht aus zwei Wörtern, getrennt durch ein Leerzeichen). Die Spalte name bleibt.

SQLDatenbank: Shop

Test

Teste dich

1. Migration 5 ist auf der Seite schon gelaufen. Sie hat einen Fehler in einem Spaltennamen. Was tust du?
2. Warum läuft eine Migration in einer Transaktion?
3. Die Seite läuft ohne Unterbrechung, und die Spalte city soll zu town werden. Was ist die sichere Reihenfolge?

Erstellt von Ivo Gergov im Rahmen der Kampagne von Evo Tech für zugängliche Programmierausbildung ·