Profi6 Min. Lesezeit

DynamoDB-Migrationen ohne Downtime

Aus SQL kommend ist eine Migration ein ALTER TABLE, das die Tabelle sperrt, während es jede Zeile neu schreibt. DynamoDB hat kein Schema zu ändern — Items sind schemalos, also ist das Hinzufügen eines Attributs oder eines neuen Entitätstyps kostenlos.

Der harte Teil ist das Zugriffsmuster, das die neuen Daten bedienen müssen, und das Umformen lebender Daten, um es zu bedienen, ohne ein Stop-the-World-Neuschreiben.

Wie migriert man eine DynamoDB-Tabelle ohne Downtime?

DynamoDB kennt kein ALTER TABLE, daher sperren Migrationen die Tabelle nie. Du fügst Attribute, eine neue Key-Form oder einen neuen online per UpdateTable hinzu und formst Live-Daten inkrementell um: Backfill alter Items entweder lazy beim Lesen oder mit einem gedrosselten Sweep, kombiniert mit Dual-Writes während der Übergangsphase. Es gibt keinen Flag-Day-Cutover.

  • Es gibt kein ALTER TABLE. Items sind schemalos. Eine „Migration" bedeutet, Attribute, eine neue Key-Form oder einen neuen Index hinzuzufügen — nie einen festen Spaltensatz neu zu schreiben.
  • Neue Schreibvorgänge sind einfach; alte Items sind das Problem. Die bestehenden Zeilen tragen die neuen Attribute nicht, also verfehlt jeder neue Index oder jede Abfrage sie still, bis du backfillst.
  • Füge Indizes online hinzu, backfille lazy. UpdateTable baut einen GSI auf einer Live-Tabelle; backfille alte Items beim Lesen (lazy) oder mit einem kontrollierten Sweep — nie ein Flag-Day-Cutover.
  • Dual-Write über die Transition hinweg. Solange beide Formen koexistieren, schreibe das alte und neue Format zusammen, sodass kein Lesepfad veraltet.

Rahme es als Zugriffsmuster, nicht als Spalte

Angenommen, du betreibst ein SaaS-Workspace-Produkt auf einer Tabelle. Items verwenden PK = "WS#<id>" und SK, überladen pro Entität:

PKSKattributes
WS#a91METAname, tier
WS#a91DOC#2026-04-01#x7title, author, body
WS#a91DOC#2026-04-02#k2title, author, body

Jetzt will das Produkt Kommentare zu Dokumenten, plus einen neuen Lesevorgang: „liste jeden Kommentar auf, den ein Mitglied über den Workspace geschrieben hat, neueste zuerst." Diese letzte Klausel ist die Migration. Ein neuer Entitätstyp allein ist trivial; eine Abfrage zu bedienen, die die aktuellen Keys nicht beantworten können, ist die Arbeit.

Füge zuerst den neuen Entitätstyp hinzu

Kommentare sind nur neue Items in derselben Partition — keine Migrationszeremonie, keine neue Tabelle:

PKSKattributes
WS#a91DOC#2026-04-01#x7#CMT#01HZ...author, text, createdAt

Ein Query auf PK = "WS#a91" mit SK begins_with "DOC#2026-04-01#x7#CMT#" listet bereits die Kommentare eines Dokuments auf. Bestehende Dokumente bleiben unberührt. Diese Hälfte geht an Tag eins live — siehe Item Collections und überladene Keys dafür, warum dieselbe Partition beides hält.

Die neue Abfrage braucht einen GSI

„Alle Kommentare eines Mitglieds, neueste zuerst" kann von der Basistabelle nicht bedient werden — memberId ist weder der PK noch ein SK-Präfix. Das ist ein neuer Index, und ihn korrekt zu wählen ist eine eigene Entscheidung: siehe GSI vs. LSI (ein LSI muss bei der Tabellenerstellung existieren, also ist für eine Migration auf einer Live-Tabelle ein GSI deine einzige Option).

Füge einen generischen GSI1 hinzu und schreibe die neuen Attribute auf neue Kommentar-Items:

GSI1PKGSI1SK
MEMBER#u442026-04-02T09:15:00Z

Query GSI1 WHERE GSI1PK = "MEMBER#u44" mit ScanIndexForward = false gibt Kommentare pro Mitglied neueste-zuerst.

Baue den Index online

UpdateTable fügt einer Live-Tabelle einen GSI ohne Downtime hinzu. DynamoDB backfillt bestehende Items im Hintergrund in den Index; der Index meldet CREATING/Backfilling, bis es fertig ist, dann kippt er auf ACTIVE (Managing GSIs).

UpdateTable: GSI1 hinzufügenIndex-Status: CREATINGBestehende Items backfillenStatus: ACTIVEQuery GSI1 sicher

Zwei Fallen hier. Erstens warnt AWS, dass das Hinzufügen eines GSI Basistabellen-Schreibvorgänge throtteln kann, wenn der neue Key ungleichmäßig verteilt — füge ihn in einem verkehrsarmen Fenster hinzu und beobachte CloudWatch. Zweitens ist der Index letztendlich konsistent, selbst nachdem er ACTIVE wird; ein Schreibvorgang ist auf dem GSI möglicherweise einen Moment lang nicht sichtbar. Siehe warum GSIs letztendlich konsistent sind.

Backfille die alten Items

Der GSI indexiert nur Items, die GSI1PK/GSI1SK haben. Deine Pre-Migrations-Kommentare — geschrieben, bevor das Attribut existierte — erscheinen nie, selbst nachdem der Backfill abgeschlossen ist. Der Online-GSI-Backfill kopiert bestehende Items, aber er kann keine Attribute erfinden, die nicht auf ihnen sind. Du musst die Werte hinzufügen.

Zwei Strategien:

StrategieWie es funktioniertVerwenden wenn
LazyBeim Lesen eines alten Items die neuen Attribute zurückschreibenAlte Items werden oft gelesen; rinne die Kosten
SweepEin paginierter Scan aktualisiert jedes alte Item einmalDu brauchst den GSI bis zu einer Deadline komplett

Für den Sweep blättere mit Scan durch und füge für jeden alten Kommentar die Index-Attribute mit einem bedingten UpdateItem hinzu, sodass du nie einen gleichzeitigen Schreibvorgang überschreibst.

Die Bedingung sichert darauf ab, dass das Attribut noch nicht existiert. Baue und kopiere die exakte ConditionExpression und UpdateExpression mit dem DynamoDB Expression Builder, statt attribute_not_exists(GSI1PK) von Hand zu tippen.

Dual-Write durch die Transition

Bis jedes alte Item die neuen Attribute trägt, koexistieren zwei Formen. Der Schreibpfad muss das neue Format bei jedem Schreibvorgang befüllen — neue Kommentare und jedes Update eines alten — sodass die Lücke nur schrumpft.

Wähle eine Backfill-Endbedingung, die du verifizieren kannst: Der Sweep hat die ganze Tabelle durchblättert, oder der Lazy-Pfad lief lange genug, dass nicht-konvertierte Items von Natur aus veraltet sind. Erst dann entferne den alten Lesepfad. Dies zu überspringen ist, wie eine Migration „abschließt", während ein Bruchteil der Abfragen still zu kurze Ergebnisse zurückgibt.

Eine Tabelle in DynoTable durchblättern, um Items zu erkennen, denen während eines Backfills die neuen Index-Attribute fehlen.
Eine Tabelle in DynoTable durchblättern, um Items zu erkennen, denen während eines Backfills die neuen Index-Attribute fehlen.

Fallstricke

  • Das Attribut hinzufügen ≠ backfilled. Ein neuer GSI startet für alte Items leer. Verifiziere die Abdeckung, bevor du der Abfrage vertraust.
  • Einen Key an Ort und Stelle zu ändern ist keine Migration — es ist ein Neuschreiben. Du kannst den PK/SK eines Items nicht mutieren; du schreibst ein neues Item unter dem neuen Key und löschst das alte. Plane es als Copy-then-Delete, Dual-Read dazwischen.
  • Kein transaktionaler Cutover. Es gibt keinen Moment, in dem die ganze Tabelle kippt. Gestalte jeden Schritt so, dass er sicher ist, während beide Formen live sind.

Nächste Schritte

Prüfe die neuen Keys und überladenen Collections im Single-Table-Design und bestätige, dass der Backfill komplett ist, indem du die Live-Tabelle durchblätterst. Probiere DynoTable aus, um deine Tabelle zu durchsuchen, un-backfilled Items zu erkennen und die bedingten Updates gegen deine eigenen Daten auszuführen.

Aktualisiert