Jetzt reparieren
- Datei ablegen
- Reparatur läuft lokal
- Ergebnis herunterladen
Die History-Datei ist eine standardmäßige SQLite-Datenbank (16-Byte-Magic SQLite format 3\0). Wenn ein Werkzeug also database disk image is malformed zu ihr meldet oder Chrome nach einem Absturz deinen Verlauf verliert, ist das dieselbe Fehlerklasse, die jede SQLite-Datei treffen kann: eine beschädigte Seite oder ein beschädigter Zeiger, kein flächiger Datenverlust. Zieh die History-Datei oben hinein, und der Scanner öffnet sie in deinem Browser, läuft direkt durch die Seiten, baut das Schema neu auf und fügt jede Zeile, die er noch dekodieren kann, in eine frische, öffenbare Datenbank ein — die Datei verlässt deinen Rechner nie.
Chromes History ist eine SQLite-Datenbank ohne Dateiendung
Dein Verlauf wird nicht in irgendeinem proprietären Format gespeichert — er ist eine SQLite-Datenbank, die im Profilverzeichnis von Chrome liegt: unter Windows %LOCALAPPDATA%\Google\Chrome\User Data\Default\History, unter macOS ~/Library/Application Support/Google/Chrome/Default/History und unter Linux ~/.config/google-chrome/Default/History (Chromium nutzt ~/.config/chromium/…, Edge …/Microsoft/Edge/…, Brave …/BraveSoftware/Brave-Browser/…). Die Datei heißt History ohne Endung, und deshalb kommen viele nicht darauf, dass sie sich in jedem SQLite-Werkzeug öffnen lässt — benenne eine Kopie in History.db um, und DB Browser for SQLite liest sie auf der Stelle.
Darin stecken die Tabellen, aus denen sich dein Browserprotokoll zusammensetzt. urls hält eine Zeile pro besuchter Seite — ihre Spalten sind id, url, title, visit_count, typed_count, last_visit_time und hidden. visits ist die Zeitleiste: jede Zeile hat einen Fremdschlüssel url, der zurück auf urls.id verweist, ein visit_time, ein from_visit, das auf den vorherigen Besuch zeigt (so lassen sich die Vor-/Zurück-Ketten rekonstruieren), und eine Bitmaske transition, deren niederwertiges Byte den Kerntyp angibt (LINK = 0, TYPED = 1, AUTO_BOOKMARK = 2, RELOAD = 8). Daneben liegen keyword_search_terms, downloads und downloads_url_chains, segments/segment_usage (die die Verknüpfungen auf der Neuer-Tab-Seite speisen) und eine kleine Tabelle meta mit den Zeilen version und last_compatible_version, die Chrome sagen, welches Schema es vor sich hat.
Ein Detail bringt jeden ins Straucheln, der den Verlauf exportiert: die Zeitstempel sind keine Unix-Zeit. last_visit_time und visit_time werden als Mikrosekunden seit dem 1601-01-01 00:00:00 UTC gespeichert (die Chrome/WebKit-Epoche). Um einen davon als normales Datum zu lesen, teilst du durch 1.000.000 und ziehst 11.644.473.600 Sekunden ab. Die Wiederherstellung bewahrt die rohen Ganzzahlen genau so, wie sie auf der Platte liegen, sodass die Daten den Neuaufbau überleben — du rechnest sie einfach hinterher um.
Wie die History-Datei malformed wird: Seiten und Zeiger
Eine SQLite-Datenbank ist ein flaches Feld aus Seiten fester Größe — Chrome nutzt den Standardwert von 4096 Byte. Seite 1 trägt den Header und das Schema; jede Tabelle, einschließlich urls und visits, ist ein B-Baum, dessen innere Seiten hinunter auf Blattseiten zeigen, die deine tatsächlichen Zeilen enthalten. Chrome betreibt die History-Datenbank im WAL-Modus (write-ahead logging), deshalb siehst du daneben normalerweise Geschwisterdateien namens History-wal und History-shm; ältere Builds und manche Profile hinterlassen stattdessen ein Rollback-Journal namens History-journal.
Genau diese Begleitmechanik ist der Ort, an dem sich der Schaden einschleicht. Fällt der Strom aus, läuft die Platte voll oder wird Chrome mitten in einem Checkpoint abgeschossen, kann ein WAL-Frame nur zur Hälfte zurück in die Hauptdatei geschrieben werden — eine einzige innere Seite bekommt einen inkonsistenten Zellzeiger oder eine Seitenzahl, die nicht zur Dateigröße passt. SQLite folgt diesem Zeiger, findet etwas, das keine gültige B-Baum-Seite ist, und bricht ab mit Error: database disk image is malformed (11) — Ergebniscode SQLITE_CORRUPT. Führst du PRAGMA integrity_check aus, siehst du die Einzelheiten: Zeilen wie *** in database main ***, Page 214: btreeInitPage() returns error code 11, row 1803 missing from index urls_url_index oder wrong # of entries in index visits_url_index.
Das Entscheidende: die Engine hält bei der ersten Inkonsistenz an, aber die Seiten, die sie nie erreicht hat, sind meist tadellos, und deine Zeilen liegen weiterhin unberührt in ihren Blattseiten. Es ist dieselbe Geschichte wie beim fehlenden moov-Index eines Videos oder dem kaputten zentralen Verzeichnis eines ZIP — die Karte ist zerbrochen, nicht die Daten. Deshalb holt ein Neuaufbau auf Seitenebene dort so viel zurück, wo das normale Öffnen der Datei nichts zurückholt.
Was die Wiederherstellung wirklich zurückholt
Eine malformed History-Datei repariert man nicht an Ort und Stelle — man liest alles noch Dekodierbare aus und schreibt es in eine brandneue Datenbank, genau so, wie der SQLite-eigene Befehl .recover arbeitet. Der Scanner liest jede Seite lokal, rekonstruiert das Schema aus den überlebenden Definitionen und läuft dann durch den B-Baum jeder Tabelle und dekodiert die selbstbeschreibenden Datensätze in ihren Blattseiten. Zeilen, die die Zeigerkette nicht mehr erreichen kann, werden durch einen rohen Seiten-Sweep gefunden, und alles, was sich dekodieren lässt, aber zu keiner bekannten Tabelle passt, wird in eine Tabelle lost_and_found geschrieben, statt es wegzuwerfen.
In der Praxis bringt das die Substanz deines Verlaufs zurück: die Tabelle urls (Adressen, Seitentitel, visit_count, last_visit_time), die Zeitleiste visits mit ihren transition-Typen und from_visit-Ketten und — wo ihre Seiten intakt sind — keyword_search_terms, downloads und die segments-Daten. Wenn du noch die Geschwisterdatei History-wal hast, füge sie im optionalen Feld hinzu, nachdem du die Hauptdatei hineingezogen hast: ihre bestätigten Frames werden vor dem Scan überlagert, sodass der Neuaufbau die letzte bestätigte Transaktion statt des letzten Checkpoints widerspiegelt — oft die neuesten paar Stunden Surfen. Das Ergebnis ist eine frische, öffenbare SQLite-Datei, die du herunterlädst; benenne sie zurück in History, leg sie bei geschlossenem Chrome in den Profilordner, und dein Verlauf ist wieder da — oder frag sie einfach in einem beliebigen SQLite-Viewer ab.
Wo sie wirklich an ihre Grenze stößt
Die Wiederherstellung gibt zurück, was physisch vorhanden ist; sie kann nicht erfinden, was überschrieben wurde. Zeilen, die am Ende der Datei abgeschnitten wurden, oder deren Seiten nach einem Löschvorgang wiederverwendet wurden, sind weg — kein Werkzeug bringt die zurück. Der mit Abstand größte Verlust speziell bei Chrome ist die Zeit: wenn Chrome eine History-Datei öffnet, die es für malformed hält, löscht es sie häufig und legt auf der Stelle eine frische, leere an, sodass das beschädigte Original an Ort und Stelle überschrieben wird. Ist das bereits passiert, schließe Chrome sofort und stelle aus einem Backup oder einer Kopie der alten History/History-wal wieder her — in der leeren Datei, die es ersetzt hat, gibt es nichts zu finden.
Zwei kleinere Vorbehalte, klar gesagt. Wiederhergestellte Werte kommen als ihre On-Disk-Speicherklasse zurück, sodass die deklarierte Affinität einer Spalte womöglich nicht erneut angewendet wird — die Zeitstempel sind weiterhin die korrekten Mikrosekunden-Ganzzahlen, du rechnest sie nur selbst um. Und wiederhergestellte Daten aus einer beschädigten Datenbank sind immer verdächtig: das sagt die SQLite-Dokumentation selbst, und weil ein roher Scan auch Freelist-Seiten liest, kann eine zuvor gelöschte URL gelegentlich wieder auftauchen. Der Wiederherstellungsbericht sagt Tabelle für Tabelle, was herauskam und was der rohe Scan herausgezogen hat. Nichts davon braucht einen Server: die History-Datei — die eine Karte all der Orte ist, an denen du gewesen bist — wird von deiner Platte gelesen und in deinem Tab neu aufgebaut, und du kannst im Netzwerk-Tab nachsehen, um zu bestätigen, dass 0 Byte hinausgehen.
Was sich reparieren lässt und was nicht
Kann repariert werden
- "database disk image is malformed (11)" an der History-Datei von Chrome/Chromium durch eine beschädigte Seite oder einen beschädigten B-Baum-Zeiger
- Die Tabelle urls — Adressen, Seitentitel, visit_count, typed_count und last_visit_time — aus den überlebenden Blattseiten
- Die visits-Zeitleiste: visit_time, transition-Typen und from_visit-Ketten für Vor/Zurück
- keyword_search_terms, downloads und die segments-Daten, wo ihre Seiten intakt sind
- Unbestätigtes Surfen aus einer beigefügten Geschwisterdatei History-wal (vor dem Scan überlagert)
- Beschädigte Header-Felder (falsche Seitengröße oder Seitenzahl) mit intakten Seiten dahinter
Kann nicht repariert werden
- Ein Verlauf, den Chrome bereits gelöscht und durch eine frische, leere Datei ersetzt hat — die alten Zeilen wurden an Ort und Stelle überschrieben
- Zeilen, die physisch am Ende der Datei abgeschnitten wurden, oder auf Seiten, die nach einem Löschvorgang wiederverwendet wurden — diese Bytes existieren nicht mehr
- Eine Garantie auf Richtigkeit — wiederhergestellte Daten sind immer verdächtig; gelöschte URLs können aus Freelist-Seiten wieder auftauchen, also prüfe sie
- Die exakten Spaltenaffinitäten: Werte kommen als ihre On-Disk-Speicherklasse zurück (Zeitstempel bleiben korrekt, du rechnest sie nur wieder um)
- Eine History-Datei mit 0 Byte — das ist zuerst ein Problem der Datenrettung vom Speichergerät, bevor überhaupt ein SQLite-Neuaufbau ansteht
Wenn eine Reparatur fehlschlägt, sagen wir dir warum (fehlende Daten gegenüber beschädigter Struktur), und für eine fehlgeschlagene Reparatur wird dir nie etwas berechnet.