Jak naprawić uszkodzoną bazę danych Firefox places.sqlite?

15

Miałem pewne problemy z pamięcią RAM (kilkakrotnie bluescreen, Windows XP) i teraz uszkodzone są moje bazy danych Firefox. Firefox działa, ale moja historia nie ma, a to zgłoszenie kilku nieścisłości i błędy podczas wykonywania pragma integrity_checkna places.sqlite:

obraz dysku bazy danych jest zniekształcony

Teraz pytanie, jak naprawić bazy danych SQLite?

Konstabl
źródło
2
W przyszłości przydatne może być FEBE (rozszerzenie Firefox Environment Backup Extension). Kopiuje cały profil i pakuje go jako pojedynczą kopię zapasową. Wiem, że to nie odpowiada na twoje pytanie, ale może być pomocne w przyszłości. bit.ly/aumThw
Urda
Edytowane, aby pomóc pracownikom Google znaleźć to pytanie.
bwDraco,

Odpowiedzi:

22

Uwaga

Ponieważ Firefox musi być zamknięty, aby wykonać tę procedurę, koniecznie otwórz tę stronę w innej przeglądarce internetowej lub wydrukuj ją przed kontynuowaniem.


Po wielu godzinach pracy nad odzyskaniem bazy danych Miejsc, nawet po przeczytaniu kodu źródłowego Firefoksa, udało mi się. Oto jak to zrobiłem:

  • Pobierz najnowszą wersję powłoki SQLite i wypakuj ją do swojego folderu profilu. W systemach Windows Vista i Windows 7 znajduje się w C:\Users\<username>\AppData\Roaming\Mozilla\Firefox\Profiles\<code>.defaultfolderze.
  • Zamknij Firefox, jeśli jest uruchomiony.
  • Baza danych miejsc znajduje się w places.sqlitepliku. Jeśli plik został zastąpiony z powodu uszkodzenia, użyj places.sqlite.corruptgo do odzyskania. Utwórz kopię zapasową pliku o nazwie places.sqlite.baklub places.sqlite.corrupt.bak.
  • Użyj powłoki SQLite, aby otworzyć plik bazy danych ( sqlite3 places.sqlitelub sqlite3 places.sqlite.corrupt), a następnie wprowadź:
.output dump.sql    -- sends output to file dump.sql
.dump               -- dumps database to file
  • Ponieważ baza danych jest uszkodzona, wynikowy zrzut bazy danych nie jest kompletny i nie wszystkie odzyskane dane zostały pobrane. Aby ustalić, gdzie wystąpił błąd, wyszukaj słowo ERROR(wszystkie wielkie litery) w komentarzu SQL w pliku zrzutu dump.sql(użyłem do tego Notepad ++ ) i przeczytaj INSERTpowyższe polecenie SQL , aby ustalić tabelę. W moim przypadku uszkodzony jest stół moz_places. (Opis tabel znajdujących się w bazie danych Miejsc można znaleźć tutaj , który zawiera nieaktualny diagram ER.) Wyjaśnię, jak odzyskać dodatkowe dane tylko z tej tabeli; poniższa procedura prawdopodobnie nie ma zastosowania w przypadku innych tabel, więc pomiń te podetapy, jeśli w grę wchodzi tabela inna niż moz_places).

    • Każdy wiersz w moz_placestabeli ma identyfikator. Wiersze są zrzucane z tabeli zgodnie z kolejnością tego identyfikatora. 1 Identyfikator to pierwsza wartość po nawiasie otwierającym w INSERTinstrukcji. Obszar, w którym baza danych jest uszkodzona, prawdopodobnie będzie małym blokiem wierszy w tej tabeli; chodzi tutaj o pominięcie tego uszkodzonego obszaru i odzyskanie jak największej ilości danych. Obszar początkowy takiego bloku jest reprezentowany na zrzucie jako wiersz przed ERRORpojawieniem się komentarza. Używając identyfikatora dla tego wiersza, możemy ustalić, gdzie baza danych jest uszkodzona. Robimy to, stosując SELECTjako warunek instrukcje z identyfikatorem; ten proces wymaga prób i błędów. Na przykład, jeśli ostatnim identyfikatorem przed błędem był 49999, a błąd wystąpi później, uszkodzony blok zaczyna się od ID 50000. Użyj instrukcji takich jak:

    - tłumi niepotrzebne dane wyjściowe
    - następujące polecenie dotyczy systemów Windows
    - dla Linuksa i innych systemów uniksowych i podobnych do Unixa, użyj .output / dev / null
    .output NUL
    
    WYBIERZ id ​​z moz_places GDZIE id> = 50100;
    
    • Dostosuj wartość zgodnie z id >=i powtarzaj powyższe SELECTpolecenie, aż znajdziesz najmniejszą wartość, która nie spowoduje, że SQLite wyświetli błąd. Jest to identyfikator, który odnosi się do wiersza, od którego możemy odzyskać dodatkowe dane. Załóżmy, że ten identyfikator to 50200. Aby zrzucić te dane, wprowadź:

    .output dump2.sql
    .mode insert
    WYBIERZ * Z moz_places GDZIE id> = 50200;
    
    - przywrócić normalne zachowanie wyjściowe
    .output stdout
    lista trybów
    
    • Zauważ, że INSERTinstrukcje w dump2.sqlpliku zaczynają się od INSERT INTO table VALUES, więc użyj funkcji Znajdź i zamień w edytorze tekstu, aby zamienić wszystkie wystąpienia tego ciągu na INSERT INTO moz_places VALUES.
    • Skopiuj całą zawartość dump2.sqlpliku i wklej go do dump.sqlpliku, w którym ERRORpojawia się komentarz.
  • Zamień ROLLBACK; -- due to errorsna końcu pliku na COMMIT;.
  • Dodaj następujący kod na początku dump.sqlpliku. Zastąp <version>poprawną wartością, która jest wymagana dla Firefoksa do ustalenia wersji schematu bazy danych na podstawie wersji Firefoksa, w następujący sposób (można go znaleźć w pliku źródłowym Firefox toolkit/components/places/Database.cpp):
    • Firefox 52: wersja schematu 35
    • Firefox 53: wersja schematu 36
    • Firefox 57: wersja schematu 39
    • Firefox 58: wersja schematu 41
    • Firefox 60: wersja schematu 43
    • Firefox 61: wersja schematu 47
    • Firefox 62: wersja schematu 52
    • Firefox 69: wersja schematu 53

PRAGMA user_version = <wersja>;
PRAGMA journal_mode = obciąć;
PRAGMA page_size = 32768;
ODKURZAĆ;
PRAGMA journal_mode = wal;
  • Wyjdź z powłoki SQLite, usuń places.sqlite, a następnie uruchom powłokę SQLite, places.sqliteużywając pustej bazy danych sqlite3 places.sqlite. Wpisz, .read dump.sqlaby załadować zrzut SQL do bazy danych.
  • Uruchom Firefox i potwierdź, że Twoja historia i pasek lokalizacji działają zgodnie z przeznaczeniem. Po potwierdzeniu, że wszystko jest w porządku, usuń pliki zrzutu bazy danych i plik wykonywalny powłoki SQLite z folderu profilu.

Bardziej odpowiednie informacje można znaleźć na następujących stronach:

Procedura uproszczona jest opisana w tym artykule MDN, ale jej nie przetestowałem. Niemniej jednak dołączyłem zaktualizowane PRAGMApolecenia z tego artykułu.


1 SQL zwykle nie gwarantuje, że dane wyjściowe bazy danych będą podawane w dowolnej kolejności, chyba że użyjesz ORDER BYklauzuli. Jednak ORDER BYprawdopodobnie nie wygeneruje żadnych danych wyjściowych w uszkodzonej bazie danych (ponieważ SQLite będzie musiał odczytać całą tabelę, zanim będzie mógł wygenerować jakiekolwiek dane wyjściowe). O ile mi wiadomo, Firefox zawsze zapisuje moz_placespozycje tabeli z sekwencyjnymi identyfikatorami, więc możemy założyć, że wszystkie dane wyjściowe są uporządkowane według ID.

bwDraco
źródło
3
To czysta wspaniałość. Pomógł mi odzyskać prawie całą historię z uszkodzonego miejsca.sqlite. Wielkie dzięki!!
Ashutosh Jindal
Pomogło z dwiema modyfikacjami: 1) dodać „;” w linii user_version; 2) z jakiegoś powodu mój „uszkodzony” plik miał wersję schematu, która była „o jeden mniejsza” niż oczekiwano. Po tym, jak twoja metoda początkowo nie działała, próbowałem zaimportować zrzut do 10 MB nowej bazy danych i nie powiodło się, ponieważ stara tabela miała jedną kolumnę mniej. Spojrzenie na link do kodu źródłowego pozwoliło mi zrozumieć, co się dzieje. Świetny post!!!
Tilman Hausherr,
@TilmanHausherr: Adresowany. Aby uniknąć problemu zmiany kolumny, wykonaj czynności opisane w tej odpowiedzi, gdy tylko zauważysz uszkodzenie i przed aktualizacją Firefoksa, aby schemat bazy danych nie został zmieniony. Możesz także spróbować ustawić starszą wersję schematu - Firefox przywróci ją do nowej wersji po przywróceniu bazy danych.
bwDraco,
Ustawienie poprzedniej wersji schematu było tym, co zrobiłem podczas pisania mojego pierwszego komentarza, tj. Już mi się udało :-) Tak, podejrzewam, że nie zauważyłem od razu uszkodzenia, zwykle zauważam to tylko przy wprowadzaniu znaków, które powinny Pojawia się „stary adres URL” i nic się nie dzieje.
Tilman Hausherr
Wspaniała robota! Cieszę się, że zaktualizowałeś go, co umieściło go z powrotem w aktywnych pytaniach, w których go zauważyłem.
fixer1234
4

Cóż, w zależności od tego, jak jest uszkodzony, naprawa może nie być możliwa. Najlepszym rozwiązaniem jest prawdopodobnie próba zrzucenia bazy danych za pomocą sqlite, a następnie sprawdzenie, co można uratować.

Jeśli to się nie powiedzie, prawdopodobnie będziesz musiał przywrócić dane z kopii zapasowej.

Aby zrzucić i ponownie utworzyć bazę danych, użyj polecenia .dump:

sqlite places.sqlite .dump | sqlite places-new.sqlite
Śleske
źródło
1
Dziękuję Ci. Wpis SO nie był pomocny, ponieważ nie działał, ale działało rozwiązanie wymienione w linku d:\sqlite3.exe d:\idimager.cat.db .dump | d:\sqlite3.exe d:\newdb.cat.db. Wszystkie ulubione zniknęły, ale odbudowuję je, kiedy odwiedzam strony. Dzięki jeszcze raz!
Bobby
link stackoverflow.com/questions/2255305/... w powyższym pytaniu został dobrowolnie usunięty przez jego autora. Odpowiedź poniżej mogą być pomocne.
user66001
@ user66001: Tak, OP usunął swoje pytanie. Skopiowałem odpowiednie polecenie.
sleske,
To nie działało dla mnie, a skończyło się na places.sqlite.corruptpliku. Opublikowałem kolejną odpowiedź z rozwiązaniem, które działało dla mnie.
Daniel
2

Jak zawsze podczas przeprowadzania takiej naprawy, zalecamy wykonanie przynajmniej jednej kopii zapasowej pliku places.sqlite w katalogu profilu. Posiadanie kopii zapasowej pozwala wypróbować różne rzeczy w celu naprawy takich problemów, jednocześnie wiedząc, że jeśli próba naprawy pogorszy sytuację, zawsze możesz wykonać kolejną kopię kopii zapasowej, na której można spróbować ponownie.

W zależności od tego, co jest uszkodzone i jak bardzo jest uszkodzone, może być możliwe rozwiązanie problemów z rozszerzeniem Konserwacja miejsc . Kilka razy skończyłem z uszkodzonym plikiem places.sqlite. Miejsca Konserwacja była w stanie rozwiązać problem za każdym razem, uruchamiając różne kontrole / poprawki, które udostępnia jako operacje w oknie dialogowym opcji. Różne kontrole i / lub raportowanie powinny zająć od kilku minut do minut.

Jeśli to nie zadziała, konieczne może być przejście do ręcznej naprawy w sposób podobny do opisanego powyżej w DragonLord.

Makyen
źródło
1

Ten proces opisany w MDN pomógł mi rozwiązać problem polegający na tym, że nowe strony, które odwiedziłem, nie zostały zapisane w historii przeglądarki. Nie miałem pliku places.sqlite.corrupt(lub places.sqlite-corrupt), ale sprawdzam jego integralnośćplaces.sqlite pliku ujawniło, że obraz dysku bazy danych jest nieprawidłowo sformułowany .

Zamknij Firefoksa i zrób kopię zapasową swojego profilu Firefox, zanim przejdziesz dalej.

$ cd /Users/<username>/Library/Application\ Support/Firefox/Profiles/<profile_dir>/
$ cp places.sqlite places.sqlite.bak  # for safety

$ sqlite3 places.sqlite
sqlite> PRAGMA integrity_check;
*** in database main ***
On tree page 2 cell 131: Rowid 20884 out of order
...
Error: database disk image is malformed
sqlite> .clone places-clone.sqlite
moz_places... done
moz_historyvisits... done
... more output like above plus a few errors (which I ignored) like
sqlite_sequence... Error: object name reserved for internal use: sqlite_sequence
SQL: [CREATE TABLE sqlite_sequence(name,seq)]
done
...
sqlite> PRAGMA user_version;
43  <----- TAKE NOTE OF THIS VALUE it may be different for you
sqlite> .exit

$ sqlite3 places-clone.sqlite
sqlite> PRAGMA integrity_check;
ok
sqlite> PRAGMA user_version = 43;  -- use the number you got from PRAGMA user_version; above
sqlite> PRAGMA journal_mode = truncate;
truncate
sqlite> PRAGMA page_size = 32768;
sqlite> VACUUM;
sqlite> PRAGMA journal_mode = wal;
wal
sqlite> .exit

$ mv places-clone.sqlite places.sqlite

Uruchom Firefox. Historia powinna znów działać.

Jestem na komputerze Mac z przeglądarką Firefox 60.0.1. Konieczne może być dostosowanie poleceń dla platformy.

Daniel
źródło
Dzięki Danielu, zawsze pomocny jest faktyczna procedura polecenia
not2qubit