Jak bezpiecznie uruchamiać migracje baz danych z wieloma instancjami aplikacji?

10

Mamy aplikację, która łączy w sobie zarówno szybką (<1 sekundę), jak i powolną migrację bazy danych (> 30 sekund). W tej chwili przeprowadzamy migracje baz danych jako część CI, ale nasze narzędzie CI musi znać wszystkie parametry połączenia z bazą danych dla naszej aplikacji (w wielu środowiskach), co nie jest idealne. Chcemy zmienić ten proces, aby aplikacja uruchamiała własne migracje baz danych podczas uruchamiania.

Oto sytuacja:

Mamy wiele wystąpień tej aplikacji - około 5 w produkcji. Zadzwońmy do nich node1, ..., node5. Każda aplikacja łączy się z pojedynczą instancją SQL Server, a my nie używamy wdrożeń kroczących (o ile wiem, wszystkie aplikacje są wdrażane jednocześnie)

Problem: powiedzmy, że mamy długą migrację. W takim przypadku node1rozpoczyna się, a następnie rozpoczyna migrację. Teraz node4zaczyna się, a migracja długoterminowa jeszcze się nie zakończyła, więc node4zaczyna się także migracja -> możliwe uszkodzenie danych? Jak zapobiegniesz temu problemowi, czy problem jest wystarczająco ważny, aby się o niego martwić?

Myślałem o rozwiązaniu tego problemu za pomocą zamka rozproszonego (za pomocą etcdlub czegoś podobnego). Zasadniczo wszystkie aplikacje próbują uzyskać blokadę, tylko jedna z nich ją pobiera i uruchamia migracje, a następnie odblokowuje. Gdy reszta aplikacji uruchomi się i przejdzie do sekcji krytycznej, wszystkie migracje zostały już uruchomione, więc skrypt migracji właśnie kończy działanie.

Jednak mam przeczucie, że „to przesada, musi być prostsze rozwiązanie”, więc pomyślałem, że poproszę tutaj, aby sprawdzić, czy ktoś ma jakieś lepsze pomysły.

Ben
źródło
1
Co powiesz na użycie tabeli statusu migracji jako blokady globalnej / rozproszonej? Pojedynczy wiersz wskazywałby, czy migracja jest obecnie aktywna i ewentualnie jaka migracja została wykonana jako ostatnia.
Bart van Ingen Schenau
Czy potrzebujesz wdrażać aplikacje asynchronicznie?
Ben

Odpowiedzi:

4

Ponieważ wspomniałeś o serwerze SQL: zgodnie z poprzednim postem DBA.SE zmiany schematu można (i należy) wprowadzać do transakcji. Daje to możliwość zaprojektowania migracji tak, jak każdej innej formy równoczesnych zapisów w bazie danych - zaczynasz transakcję, a gdy się nie powiedzie, wycofujesz ją. Zapobiega to co najmniej niektórym najgorszym scenariuszom uszkodzenia bazy danych (chociaż same transakcje nie zapobiegną utracie danych, gdy występują destrukcyjne kroki migracji, takie jak usunięcie kolumny lub tabeli).

Jak dotąd jestem pewien, że będziesz potrzebować również migrationstabeli, w której są już zarejestrowane migracje, więc proces aplikacji może sprawdzić, czy konkretna migracja została już zastosowana, czy nie. Następnie użyj „WYBIERZ DO AKTUALIZACJI”, aby zaimplementować swoje migracje w ten sposób (pseudo kod):

  • Rozpocznij transakcję
  • SELECT FROM Migrations FOR UPDATE WHERE MigrationLabel='MyMigration42'
  • jeśli poprzednia instrukcja zwraca wartość, zakończ transakcję
  • zastosuj migrację (wycofaj, jeśli się nie powiedzie, zaloguj awarię i zakończ transakcję)
  • INSERT 'MyMigration42' INTO Migrations(MigrationLabel)
  • zakończyć transakcję

To buduje mechanizm blokujący bezpośrednio w teście „była już zastosowana migracja” .

Zauważ, że ten projekt - teoretycznie - pozwoli nieświadomym krokom migracji, która aplikacja faktycznie je zastosuje - możliwe, że krok 1 zostanie zastosowany przez app1, krok 2 przez app2, krok 3 przez app 3, krok 4 przez app1 znowu i tak dalej. Dobrym pomysłem jest jednak nie stosowanie migracji, dopóki używane są inne instancje aplikacji. Równoległe wdrożenie, jak wspomniano w pytaniu, może już dotyczyć tego ograniczenia.

Doktor Brown
źródło
1

Może znajdziesz bibliotekę obsługującą migrację bazy danych z wieloma węzłami.

Wiem o dwóch bibliotekach w świecie Java, obie obsługują to, czego potrzebujesz:

  • Liquibase : na podstawie często zadawanych pytań : Liquibase używa rozproszonego systemu blokowania, aby zezwolić tylko na jeden proces aktualizacji bazy danych na raz. Inne procesy będą po prostu czekać, aż zamek zostanie zwolniony.
  • Flyway : Ze strony pobierania : Bezpieczne dla wielu węzłów równolegle ✓

Prawdopodobnie istnieją także inne narzędzia dla Java i innych języków.


Jeśli nie możesz (lub nie chcesz) korzystać z takiego narzędzia, tabelę można wykorzystać jako blokadę lub nawet jako dziennik migracji, patrz przykład odpowiedzi Doc Browna .

siegi
źródło