Najlepsze praktyki dotyczące zmian schematu i migracji danych do aktywnej bazy danych bez przestojów?

43

Jak wprowadzać zmiany schematu w aktywnej bazie danych bez przestojów?

Załóżmy na przykład, że mam bazę danych PostgreSQL z tabelą zawierającą różne dane użytkownika, takie jak adresy e-mail itp., Wszystkie powiązane z określonymi użytkownikami. Gdybym chciał przenieść adresy e-mail do nowej dedykowanej tabeli, musiałbym zmienić schemat, a następnie przeprowadzić migrację danych e-mail do nowej tabeli. Jak można to zrobić bez zatrzymywania zapisów na oryginalnym stole? Z pewnością podczas gdy dane są zapisywane ze starej tabeli do nowej, nowe dane byłyby nadal zapisywane do starej tabeli i byłyby pomijane, prawda?

Wydaje mi się, że ten problem pojawia się dość często, ale nie mogę znaleźć standardowego rozwiązania tego problemu.

W tym artykule omówiono problem, ale tak naprawdę nie zrozumiałem kroku 3. Mówi, aby napisać do obu tabel, a następnie przenieść stare dane z pierwszej tabeli do nowej. Jak upewnić się, że migrujesz tylko stare dane?

(Używam PostgreSQL na Heroku .)

Dan Leary
źródło
2
Facebook opracował narzędzie do tego celu dla MySQL.
Nick Chammas
2
K. Scott Allen napisał o system zarządzania wersjami schematu tutaj . Stworzyłem DbUpdater, narzędzie typu open source do wdrażania schematów uwzględniających wersje. Więcej tutaj - http://www.tewari.info/dbupdater
jes
@NickChammas Dzięki za udostępnienie tego. Mam na to wiele pytań. Czy mógłbyś zasugerować bardziej szczegółowy samouczek, najlepiej film, który wyjaśnia takie rzeczy, jak dziennik bitów, indeksy nieklastrowane i odpowiada na pytania takie jak: 1. W jaki sposób wybranie danych z tabeli źródłowej do pliku wyjściowego zmniejszy obciążenie w porównaniu z kopiowaniem do miejsca docelowego stolik bezpośrednio. 2. Kiedy zakończy się faza kopiowania? To tylko kilka pytań, które zacząłem czytać.
Sandeepan Nath
@SandeepanNath - Przepraszam, nie znam się na narzędziu Facebooka, więc nie mogę wskazać Ci więcej zasobów. Przeczytałem o tym ogłoszenie i zamieściłem swój komentarz wiele lat temu, ale nigdy go nie użyłem.
Nick Chammas

Odpowiedzi:

27

Prawie masz już odpowiedź:

  1. Utwórz nową strukturę równolegle
  2. Zacznij pisać do obu struktur
  3. Przeprowadź migrację starych danych do nowej struktury
  4. Pisz i czytaj tylko nową strukturę
  5. Usuń stare kolumny

Jeśli chodzi o krok 3 , użyj czegoś takiego (w jednej transakcji):

Wstaw to, czego jeszcze nie ma:

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);

Zaktualizuj, co zmieniło się w międzyczasie:

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;

Nowe dane nie zostaną zmienione, ponieważ są identyczne w obu miejscach.

Erwin Brandstetter
źródło
Mam kilka pytań podczas próby zrozumienia scenariusza, dla którego zaproponowałeś tę odpowiedź - 1. Czy zmiany kodu zostaną wdrożone wraz z początkiem zmian db? 2. Dlaczego będzie potrzeba pisania do obu struktur? 3. Dlaczego nie można najpierw wywołać nowej struktury, a następnie migrować istniejące dane, a następnie wdrożyć zmiany kodu, które zapełnią nową strukturę? 4. Dlaczego trzeba dowiedzieć się, czego nie ma (twoje pierwsze zapytanie)? Czy proponujesz wstawienie w wielu próbach?
Sandeepan Nath,
2
@ SandeepanNath, aby odpowiedzieć na pytanie 3 w swoim komentarzu: ponieważ (a) przywołujesz nową strukturę, (b) migrujesz do niej dane, (c) zmieniasz kod, aby zapisywać dane w nowej strukturze zamiast starej, wtedy wszystkie zmiany danych dokonane między krokiem b i krokiem c będą istniały tylko w starej strukturze. Pytanie brzmiało, jak wprowadzać zmiany w schemacie bez przestojów. Przeczytaj uważnie tę odpowiedź ponownie.
Wildcard