Sichere Workflows für Datenbankmigrationen mit KI-Coding-Agenten
Sichere Workflows für Datenbankmigrationen halten KI-Coding-Agenten nützlich und trennen Schemaplanung, Backup-Nachweis, Prüfung und genehmigte Produktionsausführung.

Änderungen an Produktionsdatenbanken brauchen einen anderen Ablauf als gewöhnliche Codeänderungen. Ein KI-Coding-Agent kann ein Schema prüfen, Anwendungsabfragen nachverfolgen und Migrationsdateien schneller entwerfen, als die meisten Teams eine Prüfung organisieren können. Diese Geschwindigkeit darf ihm jedoch nicht die Erlaubnis geben, die Produktion zu verändern, nur weil in einem Prompt zufällig das Wort „deploy“ vorkommt.
Sichere Workflows für Datenbankmigrationen trennen Planung und Befugnis. Der Agent kann Belege und ein präzises Änderungsset vorbereiten. Ein Mensch kann die betrieblichen Folgen prüfen, die Wiederherstellung nachweisen und genau eine begrenzte Ausführung genehmigen. Diese Trennung verhindert den bekannten Fehler, bei dem ein harmlos wirkendes ALTER TABLE den Checkout blockiert, eine unkontrollierte Umschreibung auslöst oder ein halbfertiges Deployment hinterlässt, das niemand erklären kann.
Dieser Artikel verwendet PostgreSQL-Befehle, weil dessen Verhalten bei Sperren und Transaktionen in der Dokumentation klar beschrieben ist. Der Ablauf lässt sich auf andere relationale Datenbanken übertragen. PostgreSQL-Syntax und -Annahmen dürfen jedoch nicht ohne Prüfung des jeweiligen Handbuchs auf eine andere Engine übertragen werden.
Produktionsänderungen brauchen eine getrennte Befugnis zur Codegenerierung
Eine Migrationsdatei und eine Produktionsmigration sind zwei verschiedene Vorgänge. Die erste beschreibt eine Absicht. Die zweite setzt eine knappe Befugnis an einem aktiven System mit Nutzern, Replikation, Backups und möglicherweise inkompatiblen Anwendungsversionen ein.
Teams machen oft den Fehler, einem Agenten eine weitreichende Datenbankverbindung zu geben, weil die lokale Entwicklung dadurch einfacher wird. Diese Verbindung reicht dann über mehrere Umgebungen hinweg. Der Agent kann einen Staging-Host nicht von einem Produktionscluster unterscheiden, wenn beide dieselben Zugangsdaten akzeptieren. Ein Agent, der beliebiges SQL ausführen kann, hat außerdem keinen natürlichen Grund, vor einer Tabellenumschreibung innezuhalten. Er sieht eine Aufgabe und ein Werkzeug.
Teile die Arbeit in Phasen mit unterschiedlichen Eingaben und Berechtigungen:
- Die Bestandsaufnahme liest Schema-Metadaten, Migrationshistorie, Abfragecode und betriebliche Einschränkungen.
- Die Planung erstellt SQL, erwartetes Sperrverhalten, Dateneffekte, Preflight-Prüfungen, Verifikationsabfragen und eine Entscheidung zur Wiederherstellung.
- Die Prüfung bestätigt, dass der Plan zum tatsächlichen Produktionsstand passt und die Organisation das Risiko akzeptiert.
- Die Ausführung verwendet genau ein genehmigtes Artefakt für genau ein benanntes Ziel.
- Die Verifikation weist nach, dass Anwendung und Datenbank den gewünschten Zustand erreicht haben, bevor jemand das Deployment als abgeschlossen bezeichnet.
Wichtig ist die Unterscheidung zwischen Reversibilität und Wiederherstellbarkeit. Eine nullable Spalte hinzuzufügen ist oft reversibel: Eine spätere Anweisung kann sie entfernen, solange kein Code von ihr abhängt. Millionen Zeilen mit einem fehlerhaften Ausdruck zu aktualisieren, ist möglicherweise nicht reversibel, selbst wenn jemand ein scheinbares Gegen-Update schreibt. Die ursprünglichen Werte sind vielleicht nicht mehr bekannt. Wiederherstellbarkeit bedeutet, dass ein getesteter Weg existiert, den Schaden zu beheben oder einzugrenzen. Behandle beides in jedem Migrationsplan als getrennte Felder.
Ein Agent darf Produktionsbefugnisse niemals aus einem Repository-Branch, einem Ticket-Label oder einer Umgebungsvariable ableiten, die in einem Chat-Prompt steht. Solche Signale beschreiben eine Absicht, und Absichten sind häufig falsch. Die Ausführung sollte ein außerhalb des Textkontexts des Agenten ausgewähltes Ziel, ein vorbereitetes Artefakt mit dokumentiertem Digest und eine Person erfordern, die genau sieht, was ausgeführt wird.
Den Migrationsplan als prüfbares Artefakt erstellen
Ein prüfbarer Plan gibt einem Operator genug Informationen, um eine Migration vor dem Erreichen der Datenbank abzulehnen. „Einen Index hinzufügen“ ist kein Plan. Tabellengröße, Zweck der Abfrage, Indexform, Transaktionsvorgabe, Sperrwirkung und Verifikationsabfrage machen daraus einen Plan.
Lass den Agenten ein Verzeichnis mit festen Dateien erzeugen, statt nur einen Absatz in einem Pull Request. Zum Beispiel:
migrations/2025-04-add-orders-status-index/
up.sql
verify.sql
preflight.sql
recovery.md
manifest.json
Das Manifest sollte die Dateien an das vorgesehene Ziel binden und festhalten, was der Agent herausgefunden hat. Dieses Beispiel enthält keine Zugangsdaten und behauptet nicht, dass ein Backup existiert, nur weil jemand eines angefordert hat.
{
"migration_id": "2025-04-add-orders-status-index",
"engine": "postgresql",
"target": "production-orders",
"change": "create index for filtered order status query",
"transaction_mode": "outside_transaction",
"requires_backup_restore_check": true,
"expected_write_blocking": "none during index build",
"stop_conditions": [
"target schema differs from preflight result",
"backup restore check fails",
"index is invalid after execution"
]
}
Ein menschlicher Prüfer sollte aus diesem Artefakt fünf Fragen beantworten können:
- Welche Datenbank und welches Schema erhalten die Änderung?
- Welches genaue SQL wird ausgeführt, und verpackt der Runner es in eine Transaktion?
- Welche Operation blockiert, schreibt Daten neu, scannt Daten oder benötigt zusätzlichen Speicher?
- Welche Belege zeigen, dass sich die Datenbank nach einem Fehler wiederherstellen lässt?
- Welche Abfragen oder Anwendungssignale belegen den Erfolg?
Der Agent muss auch Unsicherheiten angeben. Wenn er die PostgreSQL-Version, die Tabellengröße, die aktuelle Migrationsversion oder den Kompatibilitätsbereich der aufrufenden Anwendung nicht feststellen kann, sollte er das als Abbruchbedingung nennen. Aus unvollständigem Repository-Zugriff künstliche Sicherheit abzuleiten ist schlechter, als einen Punkt offen zu lassen.
Generiertes SQL bleibt nach der Prüfung unverändert. Wenn ein Prüfer up.sql bearbeitet, muss die Prüfsumme neu erstellt und das Artefakt erneut geprüft werden. Ein häufiger Fehler beginnt mit einer geprüften Migration und endet mit einer hastig eingefügten „kleinen Korrektur“ in der Deployment-Shell. Der Live-Befehl ist dann nicht mehr der geprüfte Befehl, während das Audit-Protokoll eine beruhigende, aber falsche Geschichte erzählt.
Die Operation vor der Ausführung klassifizieren
Das SQL-Schlüsselwort sagt über das Betriebsrisiko nicht genug aus. ALTER TABLE umfasst Änderungen, die schnell abgeschlossen sind, ebenso wie Änderungen, die Sperren halten oder so viele Daten neu schreiben, dass der Speicher vollläuft. Ein sicherer Ablauf bewertet die konkrete Operation, die Datenbankversion, die Tabellengröße und die parallele Auslastung, bevor ein Ausführungspfad gewählt wird.
Die PostgreSQL-Dokumentation zu ALTER TABLE nennt den unangenehmen Teil ausdrücklich: Viele Formen erwerben eine ACCESS EXCLUSIVE-Sperre, sofern das Handbuch nichts anderes sagt. Diese Sperre steht mit Lese- und Schreibvorgängen in Konflikt. „In Staging ging es schnell“ sagt wenig aus, wenn es dort keine langen Transaktionen, keinen Berichtsbetrieb und nur einen Bruchteil der Daten gibt.
Verwende vier praktische Klassen:
| Klasse | Typisches Beispiel | Erwartung an die Ausführung |
|---|---|---|
| Nur Metadaten | Nullable Spalte ohne Standardwert hinzufügen | Kurze Operation, Sperrverhalten für die verwendete Version trotzdem prüfen |
| Paralleler Aufbau | Einen neuen Index erstellen | Spezielle Befehlsform und getrennte Transaktionsbehandlung |
| Gebatchte Datenänderung | Eine neue Spalte nachträglich befüllen | Kleine Commits, gemessene Rate, fortsetzbarer Fortschritt |
| Umschreibung oder destruktive Änderung | Den Typ einer großen Spalte ändern oder Daten löschen | Wartungsentscheidung mit ausdrücklichem Wiederherstellungsplan |
Bezeichne nicht jede Online-Operation als sicher. PostgreSQLs CREATE INDEX CONCURRENTLY verhindert laut der Dokumentation zu CREATE INDEX die Blockierung von Schreibvorgängen während des Aufbaus. Der Befehl dauert länger, darf nicht in einem Transaktionsblock laufen und kann nach einem Fehler einen ungültigen Index hinterlassen. Der pauschale Rat „immer concurrently verwenden“ ignoriert diese Bedingungen. Verwende die Option, wenn Schreibverfügbarkeit wichtig ist und dein Migrationsrunner ihre Regeln unterstützt.
Eine Planungsabfrage kann dem Prüfer eine erste Schätzung für Tabellen- und Indexgröße geben:
SELECT
pg_size_pretty(pg_total_relation_size('public.orders')) AS total_size,
pg_size_pretty(pg_relation_size('public.orders')) AS table_size,
pg_size_pretty(pg_indexes_size('public.orders')) AS indexes_size;
Das erwartete Ergebnis ist eine Zeile mit drei lesbaren Größen. Betrachte es als Größenindikator, nicht als Zusage für eine bestimmte Dauer. Zeilenbreite, Cache-Zustand, parallele Schreibvorgänge, Replikation, Festplattendurchsatz und aktive Transaktionen verändern das Ergebnis.
Der Agent sollte vor einer Operation mit nennenswerter Sperrwirkung auch Blockierer prüfen. PostgreSQL stellt aktive Sitzungen in pg_stat_activity bereit, gibt damit aber keine Erlaubnis, sie zu beenden. Der Plan sollte den Verantwortlichen für eine lang laufende Arbeitslast nennen und festlegen, ob die Migration wartet, verschoben wird oder ein Wartungsfenster erhält.
Ein wiederhergestelltes Backup ist die Eintrittskarte
Ein erfolgreicher Backup-Befehl beweist, dass ein Programm eine Datei geschrieben hat. Er beweist nicht, dass sich die Datei wiederherstellen lässt, die benötigten Objekte enthält oder dass das Wiederherstellungsverfahren unter Druck funktioniert. Vor destruktiver oder schwer umkehrbarer Arbeit muss ein Restore-Check laufen.
Für eine PostgreSQL-Datenbank kann ein logischer Dump im Custom-Format so aussehen:
pg_dump -Fc -d "$SOURCE_DATABASE" -f "orders-preflight.dump"
pg_restore -l "orders-preflight.dump" | sed -n '1,12p'
createdb migration_restore_check
pg_restore -d migration_restore_check "orders-preflight.dump"
psql -d migration_restore_check -c "SELECT count(*) FROM public.orders;"
Der Listing-Befehl sollte Archiveinträge wie eine Tabellendefinition, einen Tabellendatensatz und Indexdefinitionen ausgeben. Die letzte Abfrage sollte ein einspaltiges Ergebnis mit der Zahl der wiederhergestellten Zeilen liefern. Erfasse Befehlsausgang, Dump-Kennung, Restore-Ziel und Prüfergebnis im Migrationsdatensatz. Datenbank-URLs und Passwörter gehören nicht dorthin.
Ein logischer Restore-Check ersetzt keinen physischen Wiederherstellungstest, keine Point-in-Time-Recovery, keine Übung zur Beförderung eines Replikats und keine Backup-Zusage des Anbieters. Er beantwortet eine engere Frage: Lässt sich dieser Dump in einer Datenbank wiederherstellen und liefert er die erwarteten Objekte und Datenstrukturen? Auch diese begrenzte Antwort entdeckt beschädigte Archive, fehlende Erweiterungen, Rollenprobleme und Verfahren, die nur auf dem Laptop ihres Erstellers funktioniert haben.
Lege die Wiederherstellungsmethode vor der Ausführung fest, nicht erst nach einem Fehler. Der Plan sollte sagen, welcher dieser Fälle gilt:
- Eine Gegenmigration ist sicher, weil keine Daten verworfen wurden und die Anwendung eine Rückkehr verträgt.
- Die Wiederherstellung in einer Ersatzdatenbank ist der Weg, wobei ein Verantwortlicher den Umschaltzeitpunkt festlegt.
- Ein Replikat oder ein Wiederherstellungsverfahren des Anbieters ist der Weg, mit dokumentiertem Recovery Point Objective.
- Die Änderung lässt sich nicht sauber wiederherstellen und braucht deshalb ein Wartungsfenster sowie eine ausdrückliche Risikoakzeptanz.
Die letzte Kategorie ist legitim. Einen Rollback vorzutäuschen, weil eine Deployment-Vorlage ein entsprechendes Feld verlangt, ist es nicht. Teams schreiben mitunter DROP COLUMN als Rollback für ein Backfill, das Kundendaten verändert hat. Später stellen sie fest, dass das Löschen der neuen Spalte nur ihre Belege entfernt hat, während die alten Werte weiterhin falsch waren.
Erst erweitern, später entfernen
Die meisten schemaändernden Eingriffe an Anwendungen sollten die Kompatibilität gemischter Anwendungsversionen erhalten. Während eines Deployments können alte und neue Prozesse gleichzeitig laufen, weil Worker langsam auslaufen, Nutzer Anfragen offen halten oder ein Rollback einen älteren Build startet. Eine Migration, die von einer einzigen, sofortigen Anwendungsversion ausgeht, macht normales Deployment-Verhalten zum Ausfall.
Angenommen, orders.status_text soll durch das beschränkte orders.status_code ersetzt werden. Die unsichere Variante fügt die neue Spalte hinzu, schreibt jede Zeile um, tauscht den Anwendungscode aus und entfernt die alte Spalte in einem Release. Sie hat mehrere Fehlerstellen und keinen ruhigen Haltepunkt.
Verwende stattdessen eine Expand-and-Contract-Sequenz:
- Füge
status_codeals nullable Spalte hinzu und ergänze Strukturen, die die aktuelle Anwendung nicht stören. - Veröffentliche Anwendungscode, der das neue Feld verwendet, wenn es vorhanden ist, und beide Felder schreibt oder eines sicher aus dem anderen ableitet.
- Befülle vorhandene Zeilen in begrenzten Batches und speichere den Fortschritt außerhalb des flüchtigen Chat-Kontexts des Agenten.
- Prüfe, dass alle Zeilen die neue Invariante erfüllen und Leser das neue Feld verwenden.
- Stoppe in einem späteren Release das Schreiben in das alte Feld, warte die vereinbarte Aufbewahrungsfrist ab und entferne es erst dann.
Die Batch-Schleife ist wichtig. Ein riesiges UPDATE hält Ressourcen zu lange, erzeugt einen Schub an Write-Ahead-Log, belastet Replikate und erschwert die Wiederherstellung. Eine begrenzte Abfrage schafft zwischen Commits einen Punkt, an dem Replikationsverzug, Fehlerrate und Datenbanklast geprüft werden können.
Dieses PostgreSQL-Muster aktualisiert einen ausgewählten Batch nach Primärschlüssel und gibt die geänderten Zeilen zurück:
WITH batch AS (
SELECT id
FROM public.orders
WHERE status_code IS NULL
ORDER BY id
FOR UPDATE SKIP LOCKED
LIMIT 500
)
UPDATE public.orders AS o
SET status_code = CASE o.status_text
WHEN 'new' THEN 10
WHEN 'paid' THEN 20
WHEN 'shipped' THEN 30
ELSE NULL
END
FROM batch
WHERE o.id = batch.id
RETURNING o.id;
Der Runner wiederholt dies nur, solange Zeilen zurückgegeben werden und die Zuordnung akzeptable Werte erzeugt. SKIP LOCKED kann für einen kontrollierten Worker geeignet sein, weil es das Warten auf Zeilen vermeidet, die eine andere Transaktion hält. Es beweist nicht, dass jede Zeile verarbeitet wurde. Die Verifikationsabfrage muss verbleibende Nullwerte und unerwartete Quellwerte prüfen:
SELECT status_text, count(*)
FROM public.orders
WHERE status_code IS NULL
GROUP BY status_text
ORDER BY count(*) DESC;
Gibt die Abfrage einen unbekannten Wert zurück, muss die Migration stoppen. Ein Agent darf nicht entscheiden, dass ein unbekannter Produktionszustand zu einem Standardwert eines Enums werden kann, nur weil er die Aufgabe abschließen möchte.
Die Ausführung braucht harte Abbruchbedingungen und begrenzte Befehle
Eine genehmigte Migration kann auf einen anderen Produktionsstand treffen als den, den der Planer untersucht hat. Der Runner muss unmittelbar vor der Ausführung Preflight-Prüfungen durchführen und bei Abweichungen stoppen. So wird ein Ablauf sicherer als ein Runbook, das jemand aus dem Gedächtnis befolgt.
Verwende einen dedizierten Executor, der nur eine Artefaktkennung und einen Zielselektor akzeptiert. Er sollte aus einem Terminal eingefügtes Inline-SQL ablehnen, Artefakte mit geänderter Prüfsumme zurückweisen und vor Beginn die Zielidentität ausgeben. Der Executor kann zunächst schreibgeschütztes Preflight-SQL ausführen und für den verändernden Teil anschließend eine gesonderte Genehmigung verlangen.
Setze Sitzungszeitlimits ausdrücklich. PostgreSQL dokumentiert lock_timeout und statement_timeout als getrennte Steuerungen. Der erste bricht das Warten auf eine Sperre ab, der zweite eine zu lange laufende Anweisung. Für eine kurze Metadatenoperation kann ein Vorspann so aussehen:
SET lock_timeout = '5s';
SET statement_timeout = '60s';
SELECT current_database(), current_user, now();
Übertrage diese Zahlen nicht blind auf Indexaufbauten oder Backfills. Ein Timeout ist ein Budget, das der Plan begründen muss. Wenn ein Befehl unter erwarteter Last dreißig Minuten benötigt, erzeugt ein Statement-Timeout von sechzig Sekunden nur einen vorhersehbaren Fehler. Für eine parallele Indexerstellung braucht der Runner einen Pfad, der den Befehl nicht in eine Transaktion verpackt:
CREATE INDEX CONCURRENTLY IF NOT EXISTS orders_status_code_idx
ON public.orders (status_code);
Nach diesem Befehl muss der Index geprüft werden, statt den erfolgreichen Prozessabschluss als Beweis zu nehmen. PostgreSQL speichert die Gültigkeit in Katalogmetadaten. Ein fehlgeschlagener paralleler Aufbau kann einen ungültigen Index hinterlassen, der vor einem neuen Versuch geprüft und entfernt werden muss. Diese Prüfung gehört in verify.sql, gegebenenfalls zusammen mit einem anwendungsnahen Abfrageplan.
Ein echter Abbruch braucht benannte Signale. Stoppe, wenn der Preflight eine unerwartete Migrationsversion, zu wenig Speicherreserve, einen nicht erlaubten aktiven Blockierer, ein fehlgeschlagenes Backup-Restore, eine falsche Prüfsumme oder ein Ergebnis findet, das von der Verifikationsbedingung abweicht. Der Operator sollte nicht mit einem Agenten verhandeln müssen, während die Sperrwartezeit wächst.
Die Genehmigung muss eine Person an genau einen Live-Lauf binden
Genehmigungsmüdigkeit entsteht, wenn Systeme Menschen für jeden SQL-Aufruf fragen. Dann wird reflexartig bestätigt oder die Abfrage abgeschaltet. Eine einzelne Genehmigung zu Beginn eines klar definierten Agent-Prozesses ist sinnvoll, wenn sie den Prozess identifiziert, mit dessen Ende verfällt und nicht später stillschweigend eine andere Sitzung abdeckt.
Die Genehmigung muss genug Kontext zeigen, damit eine Person den Lauf ablehnen kann: signierte Prozessidentität, ausgewähltes Ziel, Artefaktkennung, beabsichtigte Aktionsklasse und die Frage, ob der Aktionskanal schreiben kann. Ein rohes Passwort darf weder angezeigt noch vom Agenten verarbeitet werden. Die Person genehmigt die Aktion, nicht die Offenlegung eines Geheimnisses.
Sallyport passt zu dieser Grenze, weil API- und SSH-Zugangsdaten im verschlüsselten Tresor bleiben, ein MCP-fähiger Agent Aktionen über sp mcp anfordern kann und statt Klartextgeheimnissen nur Aktionsergebnisse erhält. Die getrennte Sitzungsgenehmigung und die optionale Genehmigung pro Schlüssel können dafür sorgen, dass eine Produktionsaktion an eine menschliche Entscheidung gebunden ist, ohne wiederverwendbare Zugangsdaten in den Agent-Kontext zu legen.
Halte die Genehmigung auf die Ausführungsphase begrenzt. Der Bestandsaufnahme-Agent kann einen schreibgeschützten Weg verwenden. Der Ausführungsagent erhält eine mit seinem Prozess ablaufende Sitzung und darf nur den genehmigten Aktionspfad nutzen. Sofortiger Widerruf ist wichtig, weil ein Operator einen Lauf nach einem überraschenden Preflight-Ergebnis stoppen können muss, nicht erst nach Ende des Deployment-Skripts.
Eine Policy-Sprache ersetzt kein klares Betriebsdesign, wenn das Team die Policy unter Druck nicht erklären kann. Die zuverlässige Grenze ist einfach: Ein gesperrter Zugriff verweigert alle Aktionen, ein neuer Ausführungsprozess braucht eine Genehmigung und besonders sensible Zugangsdaten können bei jeder Verwendung eine neue Entscheidung verlangen. Das lässt sich leichter prüfen als ein Stapel abgeleiteter Regeln, an deren Erstellung sich niemand erinnert.
Audit-Datensätze müssen die Änderung ohne Geheimnisse rekonstruieren können
Nach einer fehlgeschlagenen Migration stellen Menschen einfache Fragen: Wer hat sie ausgeführt, gegen welches Ziel, welches genaue Artefakt lief, wann wurde gestoppt und wurden Daten verändert? Ein gewöhnliches Terminalprotokoll beantwortet das selten vollständig. Es kann das Ziel auslassen, den Befehl nach einer Bereinigung der Shell-Historie verlieren oder Geheimnisse enthalten, die niemals protokolliert werden sollten.
Erfasse strukturierte Ereignisse für Planung, Genehmigung, Preflight, Ausführung, Verifikation, Widerruf und Fehler. Jedes Ereignis sollte die Migrationskennung und den Artefakt-Digest enthalten, damit ein Ermittler die Prüfung mit dem Live-Lauf verbinden kann. Erfasse die von Preflight zurückgegebene Datenbankidentität und nicht nur den vom Aufrufer gewünschten Namen.
Eine minimale Ereignisstruktur sieht so aus:
{
"event": "migration.verify",
"migration_id": "2025-04-add-orders-status-index",
"artifact_sha256": "recorded-digest",
"target_identity": "production-orders",
"result": "passed",
"observed": "index valid; query returned expected columns"
}
Vermeide SQL-Parameter, wenn sie personenbezogene Daten, Tokens oder Kundendaten enthalten können. Protokolliere stattdessen den Artefakt-Digest und eine sichere Anweisungskennung. Das Ausführungssystem kann geschützte Diagnosedaten nach einer festgelegten Aufbewahrungsrichtlinie behalten. Ein Audit-Journal sollte jedoch nützlich bleiben, ohne zu einem weiteren Geheimnisspeicher zu werden.
Manipulationsnachweise verbessern die Qualität einer Untersuchung. Ein Datensatz, den jemand nach einem schlechten Deployment ändern kann, beweist nur, dass jemand Zugriff auf einen Datensatz hatte. Bei einer Hash-Kette sollte diese unabhängig im Rahmen der Incident-Prüfung verifiziert werden. Sallyports sp audit verify prüft seine verschlüsselte Audit-Kette offline und ohne Tresorzugriff. Das ist die richtige Eigenschaft für einen Prüfer, der keine Produktionszugangsdaten erhalten sollte.
Die Verifikation muss die Arbeitslast und nicht nur das DDL prüfen
Eine Migration ist erfolgreich, wenn sich die vorgesehene Arbeitslast korrekt verhält, nicht wenn die Datenbank eine Anweisung akzeptiert. Eine neue Spalte kann existieren, während Anwendungsschreibvorgänge sie auslassen. Ein Index kann gültig sein, während die Zielabfrage ihn wegen eines anderen Prädikats oder Datentyps nicht verwendet. Eine Einschränkung kann gültig sein, während ein älterer Worker weiterhin Daten sendet, die gegen den neuen Anwendungvertrag verstoßen.
Schreibe Verifikationsabfragen vor der Ausführung, solange Prüfer ihre Annahmen noch hinterfragen können. Bei einer Indexmigration prüfst du den Katalogzustand und die Abfrage, die den Index notwendig gemacht hat. Bei einem Backfill zählst du verbleibende Zeilen, gruppierst unerwartete Quellwerte und bestätigst, dass der neue Anwendungspfad die erwartete Darstellung schreibt. Bei einer Einschränkung testest du gültige und ungültige Schreibvorgänge in einer temporären Datenbank, bevor die Produktion sie erzwingt.
PostgreSQLs EXPLAIN ist nützlich, aber leicht falsch einzusetzen. Eine Planerentscheidung hängt von Statistiken, Parameterwerten, Datenverteilung und Konfiguration ab. EXPLAIN (ANALYZE, BUFFERS) führt die Abfrage aus und misst sie. Richte es daher nicht beiläufig auf eine teure Produktionsabfrage. Verwende es mit einer repräsentativen, sicheren Abfrage und definiere ein akzeptables Ergebnis, bevor du die Ausgabe siehst. Sonst kann ein müder Operator jeden Plan nachträglich rechtfertigen.
Beobachte während und nach der Änderung Live-Signale der Anwendung: Fehlerrate, Latenz der betroffenen Abfrage, Verbindungsdruck, Replikationszustand und Worker-Fehler. Der Agent kann diese Werte sammeln und präsentieren. Der Release-Verantwortliche entscheidet jedoch, ob sie die festgelegte Abschlussbedingung erfüllen.
Plane die destruktive Entfernung nicht allein deshalb, weil das Erweiterungs-Deployment erfolgreich war. Warte, bis Beobachtbarkeit und Release-Historie zeigen, dass keine alten Prozesse mehr vom alten Schema abhängen. Führe die Entfernung anschließend als eigene geprüfte Migration aus. Diese zusätzliche Änderung ist günstiger, als bei einem Rollback festzustellen, dass der alte Build eine Spalte erwartet, die eine Stunde zuvor entfernt wurde.
Der erste Produktionslauf sollte bewusst langweilig sein
Die erste von einem Agenten unterstützte Produktionsmigration sollte eine risikoarme, gut beobachtbare Änderung sein und keine unter Last umgebaute Tabelle. Wähle eine nullable zusätzliche Spalte, einen Kommentar oder eine andere Operation, deren Verhalten du bereits kennst. Nutze sie, um Artefakterstellung, Zielauswahl, Genehmigung, Backup-Nachweis, Audit-Ereignisse, Preflight-Fehler, Ausführung und Verifikation zu testen.
Die Übung muss zeigen, dass das System Arbeit verweigern kann. Richte den Executor auf ein Ziel mit falschem Schema-Fingerprint und bestätige, dass er stoppt. Ändere die geprüfte Datei und bestätige, dass die Digest-Prüfung sie ablehnt. Widerrufe die Autorisierung während eines harmlosen Testlaufs und bestätige, dass spätere Aktionen fehlschlagen. So zeigt sich, ob die Kontrollen funktionieren, wenn sie gebraucht werden, statt nur in einem Design-Dokument vernünftig auszusehen.
Erweitere danach die erlaubten Migrationsklassen einzeln. Ein Team, das sicher eine Spalte hinzufügen kann, hat damit noch nicht bewiesen, dass es eine große Tabelle nachträglich befüllen, einen parallelen Index erstellen oder sich von einer fehlerhaften Datentransformation erholen kann. Jede Klasse braucht einen eigenen beobachteten Lauf und eigene Fehlerkriterien.
Behandle Produktionsbefugnisse als etwas, das der Agent für eine eng begrenzte Aufgabe ausleiht und danach wieder verliert. Diese Arbeitsweise verhindert mehr Schaden als jede noch so raffinierte Prompt-Anweisung.
FAQ
Darf ein KI-Coding-Agent Produktionsmigrationen ausführen?
Nein. Die Planung einer Migration ist weitgehend lesbare und reversible Arbeit. Die Ausführung kann Tabellen sperren, Speicherplatz verbrauchen oder aktive Daten verändern. Gib einem Agenten die Erlaubnis, Metadaten zu prüfen und einen Plan zu erstellen. Für den Befehl, der die Produktion verändert, ist ein separater, von einem Menschen genehmigter Lauf erforderlich.
Welchen Timeout sollte ich für eine Datenbankmigration verwenden?
Setze Timeouts nur dann, wenn die Abfrage einen begrenzten Zweck und einen sicheren Abbruchpunkt hat. PostgreSQLs lock_timeout bricht eine Anweisung ab, die zu lange auf eine Sperre wartet. statement_timeout beendet eine Anweisung, die ihr Zeitbudget überschreitet. Lege beide Werte bewusst fest, denn sie ersetzen weder Überwachung noch einen getesteten Wiederherstellungsweg.
Wie prüfe ich ein Backup vor einer Produktionsmigration?
Ein logisches Backup ist erst dann wirklich erfolgreich, wenn du es wiederherstellen, dich mit der wiederhergestellten Datenbank verbinden und für die geplante Änderung wichtige Prüfungen ausführen kannst. Prüfe mindestens die Dump-Datei, stelle sie in einem temporären Ziel wieder her und vergleiche erwartete Tabellen und Zeilenzahlen. Ein Backup, das niemand wiederhergestellt hat, bleibt eine Annahme.
Wann sollte ich CREATE INDEX CONCURRENTLY verwenden?
In der Regel ja, wenn die Tabelle groß genug ist, dass eine normale Indexerstellung zu nicht akzeptablen Sperren führen würde. PostgreSQL dokumentiert, dass CREATE INDEX CONCURRENTLY Schreibvorgänge nicht blockiert. Der Befehl dauert jedoch länger und darf nicht innerhalb eines Transaktionsblocks ausgeführt werden. Nach einem fehlgeschlagenen Versuch musst du außerdem auf ungültige Indizes achten.
Wie migriere ich eine Spalte, ohne eine ältere Anwendungsversion zu beschädigen?
Teile eine Spaltenänderung in Erweiterung, Anwendungskompatibilität, Datenmigration, Validierung und spätere Entfernung auf. Füge zuerst die neue Darstellung hinzu, lasse die Anwendung beide Formen akzeptieren, migriere die Daten in kleinen, bestätigten Batches und entferne den alten Pfad erst, wenn Belege zeigen, dass er nicht mehr verwendet wird. Eine einzelne destruktive Anweisung wirkt zwar ordentlich, lässt aber weniger Auswege.
Kann jede Datenbankmigration zurückgerollt werden?
Nach einer destruktiven Datenänderung ist ein Rollback oft unmöglich. Ein guter Plan sagt das offen und ersetzt den Rollback durch Schadensbegrenzung: Worker stoppen, den neuen Anwendungspfad deaktivieren, ein getestetes Backup wiederherstellen oder, falls vorgesehen, auf ein anderes System umschalten. Bezeichne eine ungetestete umgekehrte SQL-Anweisung nicht als Rollback-Plan.
Was sollte ein Audit-Protokoll für eine von einer KI ausgeführte Migration erfassen?
Erfasse die genaue Migrationskennung und Prüfsumme, die verantwortliche Person, das Verbindungsziel, Start- und Endzeit, SQL- oder Tool-Version, betroffene Objekte, Genehmigungsreferenz, Backup-Nachweis und das Verifikationsergebnis. Erfasse auch Fehler. Ohne diese Angaben muss ein Incident-Review die Ereignisse aus Erinnerungen rekonstruieren.
Wie sollten sich KI-Agenten bei Produktionsdatenbanken authentifizieren?
Der Agent sollte eine Verbindung erhalten, mit der er Schemata prüfen und genehmigte Migrationsbefehle ausführen kann, aber kein wiederverwendbares Administratorpasswort. Halte Geheimnisse aus seinem Kontext heraus, verknüpfe die Genehmigung mit einem bestimmten Prozess und einer Sitzung und führe für jede Aktion ein Audit-Protokoll. So begrenzt du sowohl versehentliche, durch Prompts ausgelöste Aktionen als auch den Verlust von Zugangsdaten.
Wann sollte eine Migration abgebrochen werden?
Stoppe, wenn die Zielidentität unklar ist, die Backup-Wiederherstellung fehlgeschlagen ist, der erwartete Schemastand nicht stimmt, Sperrwartezeiten das festgelegte Limit überschreiten, der freie Speicher nicht ausreicht oder das Live-Ergebnis vom Plan abweicht. Nur weiterzumachen, weil ein Deployment-Fenster geöffnet ist, verwandelt eine beherrschbare Überraschung in einen längeren Ausfall.
Welche Teile einer Datenbankmigration kann ein KI-Agent sicher automatisieren?
Die Schema-Planung lässt sich weitgehend automatisieren, weil sie überprüfbar und wiederholbar ist. Für die Produktion sollte die Automatisierung enger begrenzt sein: ein unveränderliches Artefakt, ein bekanntes Ziel, ein Zeitfenster, eine an diesen Lauf gebundene Genehmigung und Live-Prüfungen. Die sinnvolle Grenze liegt zwischen der Vorbereitung einer Änderung und der Ausübung der Befugnis, sie umzusetzen.