Best Practices für Schemaänderungen und Datenmigrationen in eine Live-Datenbank ohne Ausfallzeiten?

43

Wie nehmen Sie Schemaänderungen an einer Live-Datenbank ohne Ausfallzeit vor?

Nehmen wir zum Beispiel an, ich habe eine PostgreSQL-Datenbank mit einer Tabelle, die verschiedene Benutzerdaten wie E-Mail-Adressen usw. enthält, die jeweils bestimmten Benutzern zugeordnet sind. Wenn ich die E-Mail-Adressen in eine neue dedizierte Tabelle verschieben wollte, musste ich das Schema ändern und dann die E-Mail-Daten in die neue Tabelle migrieren. Wie kann dies geschehen, ohne die Schreibvorgänge an der Originaltabelle anzuhalten? Sicher, während Daten von der alten in die neue Tabelle geschrieben werden, werden neue Daten weiterhin in die alte Tabelle geschrieben und übersehen, oder?

Ich denke, dieses Problem tritt ziemlich häufig auf, aber ich kann keine Standardlösung finden, um damit umzugehen.

Dieser Artikel befasst sich mit dem Problem, aber ich habe Schritt 3 nicht wirklich verstanden. Er sagt, er solle in beide Tabellen schreiben und dann alte Daten von der ersten in die neue Tabelle migrieren. Wie stellen Sie sicher, dass Sie nur alte Daten migrieren?

(Ich benutze PostgreSQL auf Heroku .)

Dan Leary
quelle
2
Facebook hat hierfür ein Tool für MySQL entwickelt.
Nick Chammas
2
K. Scott Allen schrieb über ein System für die Versionen Schema Verwaltung hier . Ich habe DbUpdater erstellt, ein Open Source-Tool für die versionsbezogene Schema-Bereitstellung. Mehr hier - http://www.tewari.info/dbupdater
ash
@ NickChammas Danke, dass du das geteilt hast. Ich habe viele Fragen dazu. Könnten Sie bitte ein ausführlicheres Tutorial vorschlagen, vorzugsweise ein Video, in dem Dinge wie Bit-Protokoll, nicht gruppierte Indizes und Antworten auf folgende Fragen erläutert werden: Tisch direkt. 2. Wann endet die Kopierphase? Dies sind nur ein paar Fragen, die ich habe und die ich gerade erst zu lesen begonnen habe.
Sandeepan Nath
@ SandeepanNath - Entschuldigung, ich bin mit dem Tool von Facebook nicht so vertraut und kann Sie daher nicht auf weitere Ressourcen verweisen. Ich habe eine Ankündigung darüber gelesen und meinen Kommentar vor Jahren gepostet, aber ich habe ihn nie benutzt.
Nick Chammas

Antworten:

27

Sie haben fast schon Ihre Antwort:

  1. Legen Sie die neue Struktur parallel an
  2. Beginnen Sie, in beide Strukturen zu schreiben
  3. Migrieren Sie alte Daten in die neue Struktur
  4. Nur neue Struktur schreiben und lesen
  5. Löschen Sie alte Spalten

Verwenden Sie für Schritt 3 Folgendes (in einer Transaktion):

Fügen Sie ein, was noch nicht da ist:

INSERT INTO new_tbl (old_id, data)
SELECT old_id, data
FROM   old_tbl
WHERE  NOT EXISTS (SELECT * FROM new_tbl WHERE new_tbl.old_id = old_tbl.old_id);

Aktualisieren Sie, was sich in der Zwischenzeit geändert hat:

UPDATE new_tbl
SET    data  = old.data
USING  old_tbl
WHERE  new_tbl.old_id = old_tbl.old_id
AND    new_tbl.data IS DISTINCT FROM old_tbl.data;

Neue Daten werden nicht berührt, da sie an beiden Stellen identisch sind.

Erwin Brandstetter
quelle
Ich habe einige Fragen, während ich versuche, das Szenario zu verstehen, für das Sie diese Antwort vorgeschlagen haben: 1. Werden die Codeänderungen zusammen mit dem Beginn der Datenbankänderungen bereitgestellt? 2. Warum muss an beide Strukturen geschrieben werden? 3. Warum kann die neue Struktur nicht zuerst aufgerufen und dann die vorhandenen Daten migriert und dann die Codeänderungen implementiert werden, die die neue Struktur füllen? 4. Warum muss herausgefunden werden, was nicht vorhanden ist (Ihre erste Frage)? Schlagen Sie das Einfügen in mehreren Versuchen vor?
Sandeepan Nath
2
@SandeepanNath, um Frage 3 in Ihrem Kommentar zu beantworten: Wenn Sie (a) eine neue Struktur aufrufen, (b) Daten in diese migrieren, (c) Ihren Code ändern, um Daten in die neue Struktur anstatt in die alte zu schreiben, dann alle Datenänderungen, die zwischen Schritt b und Schritt c vorgenommen wurden, sind nur in der alten Struktur vorhanden. Die Frage war, wie Schemaänderungen ohne Ausfallzeiten vorgenommen werden können. Lesen Sie diese Antwort noch einmal sorgfältig durch.
Wildcard