Dlaczego aplikacja hostowana samodzielnie uruchamia tę samą migrację bazy danych dwa razy po ponownym wdrożeniu?

Eva Wong jest Technicznym pisarzem i stałym majsterkowiczem w ZimaSpace. Całe życie geek z pasją do homelabów i oprogramowania open-source, specjalizuje się w tłumaczeniu skomplikowanych koncepcji technicznych na przystępne, praktyczne przewodniki. Eva wierzy, że samodzielne hostowanie powinno być zabawą, a nie czymś onieśmielającym. Poprzez swoje samouczki umożliwia społeczności rozwiewanie tajemnic konfiguracji sprzętu, od budowy pierwszego NAS po opanowanie kontenerów Docker.

Jedna migracja bazy danych może uruchomić się dwukrotnie, gdy więcej niż jedna ścieżka startowa, kontener lub harmonogram uzna, że odpowiada za ten sam krok aktualizacji.

Aplikacje hostowane samodzielnie często uruchamiają migracje z poziomu entrypointu, procesu webowego, workera, sidecara, jednostki systemd, zadania cron, skryptu wdrożeniowego lub podczas startu aplikacji. Po ponownym wdrożeniu stary kontener może działać równolegle z nowym, zasada automatycznego ponownego uruchamiania może uruchomić ponownie nieudaną migrację albo dwie repliki mogą uzyskać dostęp do bazy, zanim jedna z nich zapisze informację o ukończeniu. Diagnoza powinna objąć każdego potencjalnego wykonawcę oraz potwierdzić, czy framework migracji korzysta z trwałej blokady lub rekordu historii schematu, zanim rozpocznie się naprawianie danych.

Zidentyfikuj każdy proces, który może uruchomić migrację

Przeszukaj entrypoint obrazu, polecenie Compose, polecenie workera, jednostkę systemd, zadanie cron, skrypt wdrożeniowy i dziennik uruchamiania aplikacji w poszukiwaniu polecenia migracji. Zapisz identyfikatory procesów i nazwy kontenerów z obu momentów wykonania.

Docker Compose może uruchamiać usługi zgodnie z zadeklarowanymi zależnościami, ale sama kolejność startu nie gwarantuje, że migracja na poziomie aplikacji będzie miała jednego właściciela. Oficjalne wytyczne dotyczące kolejności uruchamiania pokazują, dlaczego dostępność bazy danych i wyłączna kontrola nad migracją to dwa odrębne warunki.

Jeśli to samo polecenie występuje zarówno w entrypoincie procesu webowego, jak i w dedykowanej usłudze migracji, usuń jednego właściciela. Jeśli istnieje tylko jedno polecenie, sprawdź repliki, pętle ponownego uruchamiania oraz rekordy stanu migracji.

Sprawdź, czy stare i nowe kontenery nie nakładają się na siebie

Wyświetl kontenery działające, uruchamiające się ponownie, zatrzymane i osierocone w czasie wdrożenia. Porównaj nazwy projektów, nazwy usług, identyfikatory kontenerów i znaczniki czasu utworzenia.

Systemd dokumentuje, że zasada ponownego uruchamiania usługi może uruchomić ponownie nieudane polecenie zgodnie z ustawieniami jednostki. Jego model ponownego uruchamiania usług pomaga wyjaśnić, dlaczego launcher hosta może ponownie uruchomić migrację po zakończeniu próby w kontenerze kodem różnym od zera.

Usuwaj potwierdzone osierocone procesy wykonawcze dopiero po zachowaniu ich dzienników. Drugi znacznik czasu migracji krótko po pierwszym często oznacza ponowną próbę, a nie osobno zaplanowane zadanie.

Użyj blokady bazy danych przed zastosowaniem zmian schematu

Ustal, czy aplikacja uzyskuje blokadę na poziomie bazy danych przed odczytaniem stanu migracji i zastosowaniem zmian. Przetestuj dwa równoczesne uruchomienia w środowisku przeznaczonym do testów.

PostgreSQL udostępnia blokady doradcze do koordynacji definiowanej przez aplikację, dzięki którym jeden wykonawca migracji może wykluczyć innego, nawet gdy oba procesy uruchomią się niemal jednocześnie.

Blokada musi obejmować całe okno decyzyjne i wykonawcze. Sprawdzenie bieżącej wersji schematu przed uzyskaniem blokady nadal pozwala dwóm wykonawcom wybrać tę samą oczekującą migrację.

Zweryfikuj działanie blokad w MySQL lub MariaDB

W przypadku aplikacji zgodnych z MySQL sprawdź, czy narzędzie migracji używa nazwanej blokady, transakcji lub tabeli blokad oraz czy połączenie pozostaje aktywne przez całą migrację.

MySQL dokumentuje nazwane blokady powiązane z połączeniem, które są zwalniane po zakończeniu sesji właściciela, dlatego po awarii lub ponownym uruchomieniu trzeba je bezpiecznie uzyskać ponownie.

Awaria połączenia może zwolnić blokadę, zanim framework migracji zapisze informację o ukończeniu. Porównaj dzienniki bazy danych ze znacznikami czasu ponownego uruchomienia kontenera, aby zidentyfikować tę sekwencję.

Sprawdź tabelę historii frameworka migracji

Wyświetl identyfikatory migracji, kolejność wykonania, flagi powodzenia, sumy kontrolne i znaczniki czasu. Porównaj oba odnotowane uruchomienia z rekordami faktycznie zatwierdzonymi w bazie danych.

Flyway korzysta z tabeli historii schematu do śledzenia zastosowanych migracji i ich stanów.

Jeśli pierwsze uruchomienie zmieniło schemat, ale zakończyło się niepowodzeniem przed zapisaniem sukcesu, drugie uruchomienie może ponowić migrację, która nie została napisana jako idempotentna. Naprawiaj historię dopiero po porównaniu rzeczywistego schematu z oczekiwanym rezultatem migracji.

Sprawdź tożsamość changelogu i zmiany sum kontrolnych

Porównaj nazwy plików migracji, identyfikatory, autorów, ścieżki i sumy kontrolne przed aktualizacją obrazu oraz po niej. Ustal, czy obraz zawiera zduplikowane lub zmienione wpisy changelogu.

Liquibase rejestruje wykonane zmiany w tabeli DATABASECHANGELOG, w której tożsamość zmiany zależy od jej identyfikatora, autora i ścieżki pliku.

Przeniesienie pliku changelogu lub ponowne wygenerowanie identyfikatorów może sprawić, że wcześniej wykonana praca będzie wyglądać jak nowa, nawet gdy kod SQL jest podobny. Przywróć stabilną tożsamość migracji zamiast ręcznie usuwać szerokie zakresy historii.

Wdróż ponownie z jednym właścicielem migracji i sprawdź idempotencję

Wybierz jednego właściciela migracji, dodaj trwałą blokadę, spraw, aby usługi webowe i workery oczekiwały na pomyślne ukończenie migracji, a następnie wykonaj wdrożenie na testowej kopii bazy danych.

Artykuł ZimaSpace dotyczący granic harmonogramowania kontenerów przedstawia powiązaną zasadę: jedno zadanie konserwacyjne powinno mieć jednego potwierdzonego właściciela środowiska wykonawczego.

Problem zostaje rozwiązany, gdy równoczesne lub powtarzające się uruchomienia powodują zastosowanie jednej migracji, utworzenie jednego trwałego rekordu historii i brak drugiej modyfikacji schematu po ponownym uruchomieniu.

Często zadawane pytania

Czy dwukrotne uruchomienie migracji zawsze uszkadza bazę danych?

Nie. Migracje idempotentne mogą bezpiecznie wykrywać istniejące obiekty, ale nieidempotentne transformacje danych, tworzenie indeksów lub zmiany kolumn mogą zakończyć się niepowodzeniem albo doprowadzić do zduplikowania danych.

Czy każda replika procesu webowego powinna mieć możliwość uruchamiania migracji?

Tylko wtedy, gdy framework zapewnia niezawodną koordynację na poziomie bazy danych. Dedykowany, jednorazowy właściciel migracji jest łatwiejszy do kontrolowania we wdrożeniu na serwerze domowym.

Czy mogę ręcznie oznaczyć migrację jako ukończoną?

Tylko po potwierdzeniu, że działający schemat i dane odpowiadają oczekiwanemu rezultatowi migracji. Najpierw edytowanie historii może ukryć częściowo zastosowaną zmianę.

Wsparcie i wskazówki

Więcej do przeczytania

Get More Builds Like This

Stay in the Loop

Get updates from Zima - new products, exclusive deals, and real builds from the community.

Stay in the Loop preferences

We respect your inbox. Unsubscribe anytime.