Migracja może zmodyfikować miliony rekordów, zasilać aktywne procesy i wywoływać skutki poza bazą danych. Jeśli transformacja nie powiedzie się w połowie, przywrócenie pełnej kopii nie zawsze jest bezpieczne ani akceptowalne: po wykonaniu kopii mogły zostać zapisane nowe dane albo system nie może być niedostępny przez czas wymagany do odtworzenia.
Dlatego plan wycofania migracji danych nie powinien sprowadzać się do polecenia cofającego zmiany. Musi określać, jak zidentyfikować stan objęty problemem, które operacje można cofnąć, które wymagają kompensacji oraz kiedy lepiej naprawić problem lub wznowić proces. Decyzję należy przygotować przed uruchomieniem migracji, opierając ją na kryteriach, które zespół będzie w stanie zweryfikować pod presją.
Dlaczego przywrócenie kopii nie zawsze jest wykonalnym sposobem wycofania zmian

Kopia zapasowa pozwala odzyskać dane po określonych incydentach, ale jej przywrócenie może usunąć uzasadnione zmiany wprowadzone po jej utworzeniu. Może też spowodować niedostępność systemu, konieczność odbudowy indeksów lub utratę zapisów, które trafiły do innych systemów. W przypadku replikacji, kolejek, eksportów lub integracji odzyskanie bazy danych nie cofa automatycznie tych skutków.
Warto rozróżnić trzy działania. Odtworzenie przywraca kopię lub stan z określonego momentu; wycofanie próbuje cofnąć zmiany wprowadzone przez migrację; kompensacja stosuje nowe operacje, które korygują jej skutki. Nie są to działania równoważne: kompensacja może pozostawić historię inną niż pierwotna, nawet jeśli przywróci zgodność z regułami biznesowymi.
Wybór zależy od zakresu awarii, późniejszych zapisów i celów odzyskiwania. Przed rozpoczęciem ustal, jaka utrata danych jest dopuszczalna, jak długo może trwać przerwa i kto zatwierdza odzyskiwanie. Bez określenia tych granic zespół nie ma operacyjnych kryteriów, na podstawie których może podjąć decyzję.
Klasyfikacja każdej transformacji pod kątem możliwości odzyskania
Opisz każdy etap migracji i przypisz mu przewidziany sposób odzyskiwania:
- Odwracalna: istnieje niezawodna operacja odwrotna. Na przykład przed normalizacją pola zachowywana jest jego pierwotna wartość, którą można przywrócić bez nadpisywania późniejszych zmian.
- Podlegająca kompensacji: nie da się dokładnie odtworzyć poprzedniego stanu, ale nowa operacja może skorygować skutek zgodnie z regułą biznesową. Kompensacja powinna być jawna, audytowalna i, jeśli to możliwe, idempotentna.
- Nieodwracalna: informacje są odrzucane albo występuje skutek, którego nie da się wiarygodnie cofnąć. Wymaga to wyraźnej decyzji o akceptacji ryzyka, zachowaniu danych źródłowych i dodatkowych walidacjach.
Klasyfikacji nie należy przypisywać wyłącznie na podstawie rodzaju instrukcji SQL. Aktualizacja zbiorcza może być odwracalna, jeśli poprzednia wartość została zachowana, a współbieżność jest kontrolowana; może być nieodwracalna, jeśli w trakcie wykonania inne procesy modyfikują te same wiersze. Uwzględnij również skutki uboczne, takie jak powiadomienia, wywołania API, pobrania opłat lub wiadomości w kolejkach. Często lepiej oddzielić te działania od transformacji danych.
Ustalenie stanu początkowego i niezmienników
Przed uruchomieniem zarejestruj zakres migracji: uwzględnione encje, filtry, wersję aplikacji i zastosowane reguły. Określ punkt odniesienia za pomocą istotnych liczników, a tam, gdzie ma to wartość, również agregatów lub sum kontrolnych stabilnych zbiorów. Zapisz moment odniesienia i źródło tych danych. Sama liczba, bez określenia zakresu i kontekstu, nie pozwala zweryfikować odzyskiwania.
Niezmienniki to warunki, które muszą pozostać prawdziwe zarówno w trakcie migracji, jak i po jej zakończeniu. Mogą obejmować relacje między tabelami, unikalność, dozwolone stany, kwoty, które muszą pozostać niezmienione, lub zgodność rekordów w bazie danych z systemami połączonymi. Do każdego niezmiennika dołącz odtwarzalne zapytanie lub procedurę oraz próg akceptacji. Jeśli dane mogą ulegać uzasadnionym zmianom podczas wykonywania migracji, określ, jak odróżnić tę aktywność od skutków migracji.
W aplikacji PHP transformacje można zaimplementować jako polecenia konsolowe lub procesy robocze, zamiast polegać na długotrwałym żądaniu internetowym. Taki wybór nie eliminuje ryzyka współbieżności ani ograniczeń transakcyjnych: ustal, która jednostka pracy może być wykonana atomowo i co zrobić, jeśli proces zakończy się między dwiema operacjami.
Projektowanie partii, punktów kontrolnych i wykonywania z możliwością wznowienia
Podziel pracę na partie o jasno określonych granicach, na przykład według stabilnego, uporządkowanego klucza. Unikaj stronicowania z użyciem przesunięcia, jeśli wiersze mogą zmieniać się lub znikać w trakcie procesu; znacznik kontynuacji oparty na kluczu jest zwykle bardziej przewidywalny. Rozmiar partii powinien zapewniać równowagę między czasem trwania transakcji, obciążeniem bazy danych i łatwością wykrywania błędów.
Po każdej partii zapisz punkt kontrolny zawierający identyfikator zadania, przetworzony zakres, stan, czas i wyniki walidacji. Aktualizacja danych i przesunięcie punktu kontrolnego muszą być skoordynowane, aby partia, której nie zatwierdzono, nie została oznaczona jako przetworzona. Jeśli obu operacji nie da się wykonać w ramach jednej transakcji, zaprojektuj uzgadnianie wykrywające taki stan pośredni.
Migracja z możliwością wznowienia nie stosuje zmian ponownie bez sprawdzenia. Każda operacja musi tolerować ponowne próby albo sprawdzać, czy jej skutek już wystąpił. W PHP można w tym celu wykorzystać transakcje, ograniczenia unikalności i operacje idempotentne, zależnie od silnika i modelu danych. Przetestuj również celowe przerwania: wdrożenie, wyjątek lub utrata połączenia nie powinny pozostawić zadania bez znanego sposobu kontynuacji.
Rejestrowanie zmian w celu lokalizowania skutków i audytowania decyzji
Przypisz każdemu uruchomieniu unikalny identyfikator i rejestruj co najmniej transformację, zakres, partie, wiersze objęte przetwarzaniem, błędy oraz decyzje dotyczące odzyskiwania. W przypadku zmian, które można skompensować, zachowaj niezbędne wcześniejsze dane lub bezpieczne odwołanie do nich. Nie zapisuj bez ograniczeń w logach informacji wrażliwych; ogranicz dostęp, okres przechowywania i zakres treści do tego, co jest niezbędne do odzyskiwania i audytu.
Rejestr powinien pozwalać odpowiedzieć na konkretne pytania: które wiersze próbowano przetworzyć, które zatwierdzono, które zakończyły się błędem i jaka późniejsza operacja je zmodyfikowała. W razie potrzeby połącz logi techniczne z historią zmian biznesowych. Nie myl możliwości śledzenia zmian z kopią zapasową: rejestr musi być wystarczająco szczegółowy do swojego celu i wymaga ochrony przed utratą lub modyfikacją.
Wybór między wznowieniem, kompensacją a odtworzeniem
Z góry określ sygnały i reakcje, zamiast podejmować decyzję wyłącznie intuicyjnie po wystąpieniu błędu:
- Wznów: jeśli awaria ma charakter przejściowy, niezmienniki są zachowane, a zatwierdzone partie są zidentyfikowane. Ponawiaj ograniczoną liczbę prób i obserwuj błędy oraz obciążenie.
- Zastosuj kompensację: jeśli wprowadzone zmiany są znane i istnieje przetestowana operacja korygująca. Najpierw zatrzymaj nowe zapisy, które mogłyby wejść z nią w konflikt, i upewnij się, że kompensacja nie nadpisze prawidłowych zmian.
- Odtwórz: jeśli uszkodzenie jest rozległe, odzyskiwanie z kopii zapasowej zostało zweryfikowane, a skutki utraty lub odtwarzania późniejszych zmian są akceptowalne. Skoordynuj odzyskiwanie z replikami i integracjami.
- Zatrzymaj i eskaluj: jeśli nie da się ustalić stanu, liczniki różnią się bez wyjaśnienia albo kompensacja może spowodować dalsze szkody. Przed podjęciem działań zabezpiecz dowody.
Ustal progi wstrzymania pracy, takie jak przekroczenie dopuszczalnego odsetka błędów, naruszenie niezmiennika lub rozbieżność liczników. Określ, kto może zatwierdzić wznowienie i kto podejmuje decyzję o odtworzeniu. Czasami najbezpieczniej jest odizolować dotknięty problemem przepływ i utrzymać system w kontrolowanym stanie na czas dochodzenia.
Walidacja i zamknięcie migracji za pomocą listy kontrolnej

Zakończenie procesu nie dowodzi poprawności danych. Porównaj liczniki sprzed i po migracji z oczekiwanym zakresem, uruchom reguły biznesowe i sprawdź relacje oraz wartości skrajne. Wykorzystaj próbkowanie do kontroli konkretnych przypadków, ale nie zamiast pełnych weryfikacji, jeśli można je przeprowadzić. Jeśli istnieją odbiorcy zewnętrzni, sprawdź również ich stany i uzgodnij, jak rozbieżności zostaną skorygowane.
Przed uruchomieniem: sklasyfikuj transformacje, potwierdź kopię zapasową i możliwość odzyskiwania, przetestuj partie i ponowienia prób na reprezentatywnych danych, określ niezmienniki, progi zatrzymania, osoby odpowiedzialne i okno operacyjne. Upewnij się, że zespół ma dostęp do rejestru zmian, a procedury kompensacji lub odtworzenia zostały przetestowane.
Po uruchomieniu: zweryfikuj liczniki i reguły, przejrzyj błędy oraz skutki zewnętrzne, zachowaj rejestr wykonania i udokumentuj wszelkie wyjątki. Przechowuj informacje potrzebne do odzyskiwania przez uzgodniony okres, a gdy przestaną być potrzebne, usuń je w bezpieczny sposób. Migracja jest zamknięta dopiero wtedy, gdy wyniki można zweryfikować i podjęto jawną decyzję w sprawie nierozstrzygniętych rozbieżności.



