Startseite / Artikel / Prismas Schatten-Datenbank und Namensunstimmigkeit: Ein Betriebshandbuch

Prismas Schatten-Datenbank und Namensunstimmigkeit: Ein Betriebshandbuch

Warum prisma migrate dev darum bittet, die Datenbank zurückzusetzen, wie man eine sichere Schattendatenbank konfiguriert und wie man Prismas Groß-/Kleinschreibung auf Postgres’ snake_case umwandelt.

1028 Wörter

Zwei Beschwerden tauchen immer wieder auf, wenn Teams Prisma mit PostgreSQL einsetzen: Das Migrationswerkzeug bietet ständig an, die Entwicklungsdatenbank zu löschen, und die von ihm erstellten Tabellen ähneln in keiner Weise den Namen, die ein Postgres-Administrator verwenden würde. Beides sind dokumentierte Verhaltensweisen und kein Zeichen dafür, dass Prisma für die Produktion ungeeignet ist. Diese Anleitung erklärt, was in jedem Fall vor sich geht, und gibt Ihnen eine kurze Reihe von Regeln, mit denen Sie Ihre Daten sowie Ihre Schema-Vorgaben erhalten bleiben.

Warum prisma migrate dev vorschlägt, die Datenbank zurückzusetzen

Das typische Szenario sieht so aus: Jemand führt npx prisma migrate dev aus, der Befehl stoppt mit einem Fehler, der besagt, dass eine Tabelle oder ein Enum „bereits existiert“, und der schnellste Weg, diese Meldung zu beseitigen, scheint prisma migrate reset zu sein. Dieser Befehl löscht alle Tabellen und spielt die gesamte Migrationsgeschichte von vorne ab.

Zweck der Schattendatenbank

Während der Entwicklung verwendet Prisma Migrate eine zweite, temporäre Datenbank namens Schattendatenbank. Ihre einzige Aufgabe ist die Erkennung von Abweichungen. Bei jedem Aufruf von migrate dev erstellt Prisma eine saubere Schattendatenbank, wendet alle Migrationsdateien darauf an, analysiert das resultierende Schema und vergleicht es mit der eigentlichen Entwicklungsdatenbank.

Falls die beiden nicht übereinstimmen, wurde die Entwicklungsdatenbank außerhalb der Migrationshistorie geändert. Häufige Ursachen sind:

  • eine prisma db push, die Tabellen ohne Erstellung einer Migrationsdatei geändert hat
  • eine manuelle Änderung über einen SQL-Client
  • eine Migrationsdatei, die von einem Teamkollegen erstellt wurde, aber nie gespeichert wurde

Prisma kann nicht erkennen, welche Version der Daten Sie beibehalten möchten, weshalb es die einzige sichere automatische Option vorschlägt, die es für eine Entwicklungsdatenbank hat: Sie löschen und neu erstellen, basierend auf den Migrationsdateien.

Der nicht gut dokumentierte Fehlermodus

Was Teams überrascht, ist ein anderes Problem mit ähnlichen Symptomen. Bei verwalteten Postgres-Diensten wie Neon oder Supabase fehlt dem Datenbankbenutzer in Ihrer Verbindungszeichenkette oft die Berechtigung, Datenbanken nach Bedarf zu erstellen oder zu löschen. Dadurch kann Prisma seine temporäre Schattendatenbank nicht erstellen und es tritt ein Berechtigungsfehler auf.

Entwickler interpretieren diesen Fehler oft als „die Migrationsprozesse sind gestört“ und führen aufgrund von Ratschlägen aus Community-Threads den Befehl migrate reset aus, um ihn zu beheben. Das ist gefährlich, denn gerade der Reset-Befehl zerstört zuverlässig Daten, wenn die Verbindungszeichenkette auf eine echte Datenquelle verweist. In öffentlichen GitHub-Diskussionen kommt genau diese Geschichte vor: ein Fehler in einer Schattendatenbank, ein ungeplanter Reset als „Lösung“ und Tabellen, die mitten in einem Projekt verloren gehen.

Regeln, die Migrationsprozesse sicher halten

  • Weisen Sie Prisma eine eigene Schattendatenbank zu. Setzen Sie shadowDatabaseUrl auf eine separate Datenbank, in der Ihre Benutzer frei Tabellen erstellen und löschen können. Weisen Sie diese niemals auf eine Produktivdatenbank oder eine gemeinsam genutzte Staging-Datenbank. Je nach Prisma-Version befindet sich diese Einstellung in der Datenquellenkonfiguration der Schema-Datei oder in der Prisma-Konfigurationsdatei – überprüfen Sie daher die aktuellen Dokumentationen, wo Ihre Version sie erwartet.
  • Betrachten Sie migrate reset stets als zerstörerische Aktion. Falls es als erstes Problembehebungsverfahren vorgeschlagen wird, stoppen Sie und prüfen Sie stattdessen Anmeldeinformationen, Berechtigungen sowie Abweichungen.
  • Bedenken Sie, dass die Produktivumgebung anders ist. prisma migrate deploy wendet nur ausstehende Migrationsvorgänge an. Es erstellt niemals eine Schattendatenbank und bittet auch nie um einen Reset. Das Reset-Verhalten gehört aus Designgründen zum Entwicklungsworkflow.

PascalCase-Modelle gegenüber snake_case-Tabellen

Der zweite Konfliktpunkt betrifft die Benennung. Prismas Schema-Sprache empfiehlt Modellnamen im PascalCase-Format und Feldnamen im camelCase-Format, was mit den gängigen Konventionen in JavaScript und TypeScript übereinstimmt. In der Postgres-Welt wird in der Regel das Gegenteil erwartet: snake_case-Identifikatoren, oft mit Pluralformen für Tabellennamen.

Mit den Standardeinstellungen wird ein Modell namens User mit einem Feld firstName zu einer Tabelle namens User mit einer Spalte namens firstName. Postgres akzeptiert dies, doch Identifikatoren mit gemischten Groß- und Kleinschreibweisen müssen in rohem SQL in Anführungszeichen gesetzt werden, was für DBAs, Berichtstools sowie alle Dienste, die die Datenbank direkt lesen und nicht über Prisma zugreifen, ungewohnt erscheint.

Namen abbilden mit @map und @@map

Prisma löst dieses Problem mit zwei Attributen: @map ändert den Namen einer einzelnen Feldspalte, während @@map den Namen der Tabelle hinter einem Modell ändert. Ihr TypeScript-Code behält user.firstName bei, während die Datenbank users.first_name speichert. Die Zuordnung funktioniert gut, wird aber nicht automatisch angewendet. Sie haben zwei Optionen:

  • jedes Feld und jedes Modell manuell annotieren – das ist aufwendig, aber vollständig explizit und leicht zu überprüfen
  • die externe CLI-Tool prisma-case-format verwenden, die den Großschreibungsmodus von Schema-Dateien in Bulk umschreibt und erneut ausgeführt werden kann, damit neue Felder nicht wieder zu den Standardwerten zurückkehren

Egal, welche Option Sie wählen, entscheiden Sie sich vor der ersten Migration. Das Umbenennen von Tabellen und Spalten später bedeutet, Migrationsdateien schreiben zu müssen, die auf vorhandene Daten zugreifen, und jede raw SQL-Anfrage im Codebase muss entsprechend geändert werden.

Wie Drizzle das gleiche Problem bewältigt

Drizzle, die bekannteste TypeScript-first-Alternative, bietet eine casing-Einstellung, die camelCase-Namen im Code auf snake_case-Namen in der Datenbank für das gesamte Schema abbildet. Dies ist ein seltenes Beispiel, in dem die übliche Situation umgekehrt ist. Prisma wird im Allgemeinen als das abstraktere Werkzeug und Drizzle als das dem SQL nähere beschrieben. Dennoch macht Drizzles code-first-Schema eine globale Großschreibregelung einfach, während Prismas separates Schema-System zum Zeitpunkt der Erstellung einen solchen globalen Option als anhaltenden Funktionswunsch hinterlassen hat.

Kernpunkte

  • Ein Reset-Aufruf über migrate dev weist auf Abweichungen oder Probleme mit den Berechtigungen der Schattendatenbank hin, nicht auf beschädigte Migrationsdateien.
  • Konfigurieren Sie eine explizite, isolierte Schattendatenbank für jeden gehosteten Postgres-Anbieter.
  • Nutzen Sie niemals migrate reset als allgemeine Lösung; Produktivumgebungen verlassen sich auf migrate deploy, das nichts zurücksetzen kann.
  • Wählen Sie bereits vor der ersten Migration eine Namensstrategie mit @map und @@map (manuell oder mit prisma-case-format), und nicht danach.
  • Falls Sie Prisma im Vergleich zu Drizzle genauer prüfen möchten, behandelt unser Vergleich von raw SQL, Prisma und Drizzle die damit verbundenen Abwägungen ausführlicher.

    Zusätzliche Literatur