„Cannot commit index” czyli jak przepompować dane z częściowo przywróconej (niespójnej) bazy danych
Alexey Kovyazin, ostatnia aktualizacja 30 marca 2014
Po naprawieniu uszkodzeń często pojawia się błąd “Cannot commit index” podczas etapu przywracania. W Firebird 2.0 i nowszych jest to ostrzeżenie, a baza danych nie zostanie uruchomiona; w Firebird 1.0-1.5 i InterBase występuje to jako bardzo nieprzyjemny błąd, który zatrzymuje proces przywracania (imponujące jest zobaczyć ten błąd na końcu przywracania bazy danych o rozmiarze 200 GB).
Przyczyna błędu “Cannot commit index..” jest oczywista: uszkodzenie wpływa na integralność referencyjną bazy danych, a rekordy znikają w magiczny (z punktu widzenia serwera) sposób.
Na przykład masz tabelę “Customers” i powiązaną tabelę “Orders” odniesioną przez klucz obcy. Bez uszkodzenia nie jest możliwe naruszenie klucza obcego i usunięcie rekordu z Customers bez wcześniejszego usunięcia wszystkich zamówień odnoszących się do danego klienta. Uszkodzenie wpływa na plik bazy danych na niskim poziomie i bezpośrednio usuwa rekordy. Jakież to miłe zaskoczenie dla serwera, gdy widzi nierozwiązane odnośniki do rekordów nadrzędnych z rekordów klucza obcego.
Tutaj muszę dodać wskazówkę dotyczącą procesu przywracania: silnik przywraca wszystkie tabele z nieaktywowanymi indeksami (dzięki czemu wypełnianie tabel rekordami jest znacznie szybsze), a następnie zaczyna aktywować (tj. budować) indeksy jeden po drugim. Oznacza to, że wszystkie dane są już w bazie, gdy proces przywracania rozpoczyna etap tworzenia indeksów i widzisz błąd “Cannot commit index..”.
Cóż, pierwszym pragnieniem, gdy widzisz błąd “Cannot commit index”, jest usunięcie odpowiedniego ograniczenia klucza obcego, aby umożliwić zakończenie przywracania. Pytanie brzmi, co zrobimy z niespójną, ale pomyślnie przywróconą bazą danych: usunięty klucz obcy może być ważną częścią logiki biznesowej.
Istnieją 2 podejścia: odtworzenie brakujących danych lub usunięcie niespójnych danych. Zobaczmy, co to oznacza na przykładzie Customers-Orders powyżej.
Odtwarzanie brakujących danych
Zdecydowałeś więc, że musisz odtworzyć brakujących Customers dla niespójnych Orders. W tym celu musisz określić utracone ID. Zwykle używam zapytania SQL takiego jak to (myślę, że łatwo będzie je dostosować do odpowiednich warunków):
SELECT O.Customer_ID FROM ORDERS O WHERE NOT EXISTS ( SELECT C.Customer_ID FROM CUSTOMERS C WHERE O.Customer_ID=C.Customer_ID)
Następnie możesz ręcznie wstawić rekordy z listą brakujących kluczy głównych i uruchomić ponownie kopię zapasową/przywracanie.
Przepompowanie spójnych danych
Jeśli uważasz, że utrata niespójnych rekordów jest akceptowalna, możesz przepompować wszystkie dane z częściowo przywróconej bazy do pustej bazy i po prostu pominąć niespójne rekordy, stosując następujące podejście:
-
Pobierz darmowe narzędzie IBDataPump http://www.clevercomponents.com/demo/datapump/IBPump.zip
-
Utwórz tylko bazę metadanych z kopii zapasowej naprawionej bazy (po IBFirstAID) za pomocą polecenia
gbak -c -m -user SYSDBA -pass masterkey Disk:\Path\backup.fbk Disk:\Path\fresh.fdb
-
Uruchom IBDataPump i ustaw częściowo naprawioną bazę jako Źródło, a świeżą pustą bazę jako Cel
-
Kliknij kolejne zakładki, kliknij odpowiednie przyciski, a na 3. zakładce kliknij “Pump”. Poczekaj na zakończenie (może to być długi proces; aby mieć pewne pojęcie, możesz sprawdzić dynamikę wzrostu rozmiaru bazy docelowej).
-
W rezultacie otrzymasz bazę fresh.fdb ze spójnymi relacjami kluczy obcych - jest w pełni poprawna.
Jeśli baza ma pętlę w kluczach obcych, IBDataPump ostrzeże Cię i poda listę takich ograniczeń - jedno lub więcej z nich powinno zostać usuniętych, zanim przepompowanie będzie możliwe.
Oczywiście zdarzały się przypadki, gdy przepompowanie wymagało specjalnego podejścia, a jeśli napotkasz taką sytuację, skontaktuj się z naszym wsparciem.