Layer 8Ehrlicher Tech-Support
SoftwareSchweregrad: SystemzerstörendSQLITE_CORRUPT (11)

SQLite: beschädigte Datei retten statt zerstören

SQLite meldet eine beschädigte Datenbankdatei? Erst kopieren, dann prüfen, dann mit .recover retten — und danach die Ursache abstellen.

Aufwand:
ca. 45 Min.
Voraussetzung:
Kommandozeilenwerkzeug sqlite3, Freier Speicherplatz für eine Kopie, Lesezugriff auf das Datenverzeichnis
Gilt für:
SQLite 3

Das Symptom

Eine Anwendung, die bisher jahrelang lief, meldet plötzlich, die Datenbankdatei sei beschädigt. Manche Abfragen liefern noch Daten, andere brechen sofort ab. Ein Neustart hilft nicht, ein zweiter auch nicht. Vorausgegangen ist meist etwas Unspektakuläres: ein Stromausfall, ein abgezogener Speicherstick, ein Aufräumen im Datenverzeichnis oder eine Datei, die auf einer Netzfreigabe liegt und von zwei Rechnern gleichzeitig benutzt wird.

Die „Layer 8“-Wahrheit

SQLite ist bemerkenswert schwer kaputtzukriegen. Selbst wenn mitten in einer Transaktion die Anwendung abstürzt, das Betriebssystem stirbt oder der Strom ausfällt, soll die halb geschriebene Transaktion beim nächsten Zugriff automatisch zurückgenommen werden. Wenn eine SQLite-Datei also beschädigt ist, hat in aller Regel etwas außerhalb von SQLite nicht gehalten, was es versprochen hat: ein Dateisystem, dessen Sperren nur so tun als ob, ein Datenträger, der einen Schreibvorgang als erledigt meldet, während die Daten noch im Puffer liegen, oder ein Mensch, der die Journaldatei weggeräumt hat, weil sie im Verzeichnis so unordentlich aussah.

Das ist etwas völlig anderes als die vertraute Meldung, die Datenbank sei gesperrt. Eine Sperre ist der Normalbetrieb: Zwei wollen gleichzeitig schreiben, einer wartet, alles ist heil. Eine beschädigte Datei ist kein Wartezustand, sondern ein Schaden — und Warten hilft hier nichts.

Der teuerste Fehler passiert jetzt, in den ersten fünf Minuten. Wer im Reflex auf dem Original herumprobiert, Werkzeuge darauf loslässt oder die störenden Zusatzdateien löscht, vernichtet genau die Reste, an denen die Rettung hängt. Die Reihenfolge ist immer dieselbe: kopieren, prüfen, aus der Kopie retten, in eine neue Datei einspielen, Ergebnis kontrollieren. Und erst danach die eigentliche Frage stellen, nämlich welche Umgebung diese Datei zerlegt hat — denn eine gerettete Datenbank auf demselben Netzlaufwerk ist nur eine Verabredung zum nächsten Mal.

Die echte, verifizierte Lösung

1000 % faktenbasiert. Jeder Befehl ist real, jeder Pfad existiert. Schritt für Schritt:

  1. 1.

    Sofort eine Kopie anlegen und nichts überschreiben

    Vorsicht: Jeder Rettungsversuch auf dem Original kann den Rest zerstören. Zuerst die Datenbankdatei samt ihrer Begleitdateien wegkopieren — auch die Journal- beziehungsweise WAL-Dateien, denn ohne sie fällt die automatische Wiederherstellung nach einem Absturz aus. Ab hier wird ausschließlich mit der Kopie gearbeitet:

    mkdir -p /tmp/sqlite-sicherung
    cp -a meine.db* /tmp/sqlite-sicherung/
    
  2. 2.

    Den Schaden feststellen statt raten

    Erst prüfen, ob die Datei wirklich beschädigt ist oder ob nur eine Anwendung Unsinn meldet. Die Prüfung liefert bei einer gesunden Datenbank genau eine Zeile mit dem Wert ok, sonst eine Liste der gefundenen Probleme:

    sqlite3 /tmp/sqlite-sicherung/meine.db 'PRAGMA integrity_check;'
    
  3. 3.

    Die Daten mit .recover herausholen

    Der Rettungsbefehl setzt den Inhalt direkt aus den lesbaren Seiten der Datei zusammen und schreibt ihn als Textfassung heraus. Diese Textfassung wird anschließend in eine frische, leere Datenbank eingespielt — niemals zurück in die beschädigte:

    sqlite3 /tmp/sqlite-sicherung/meine.db '.recover' > rettung.sql
    sqlite3 neu.db < rettung.sql
    
  4. 4.

    Das Ergebnis gegenprüfen

    Die neue Datei prüfen und stichprobenartig zählen, ob die Datenmengen plausibel sind. Erst wenn die Prüfung ok meldet und die Zahlen zur Erwartung passen, ist die Rettung mehr als ein Gefühl:

    sqlite3 neu.db 'PRAGMA integrity_check;'
    sqlite3 neu.db 'SELECT count(*) FROM meine_tabelle;'
    
  5. 5.

    Journaldateien in Ruhe lassen

    Ein verbreiteter Selbstmord aus Aufräumdrang: Nach einem Absturz liegen neben der Datenbank Dateien mit den Endungen -journal, -wal und -shm herum, und jemand löscht sie, weil sie stören. SQLite braucht diese Dateien, um nach einem Absturz oder Stromausfall wiederherzustellen. Werden sie verschoben, gelöscht oder umbenannt, findet die automatische Wiederherstellung nicht mehr statt und die Datenbank kann kaputtgehen. Also stehen lassen — sie verschwinden von selbst, wenn SQLite fertig ist.

  6. 6.

    Die Ursache abstellen

    Eine gerettete Datenbank ist wertlos, wenn dieselbe Umgebung sie erneut zerlegt. Die häufigsten Ursachen laut SQLite: eine Datenbankdatei auf einem Netzdateisystem, dessen Sperren nicht zuverlässig arbeiten, und billiger Wechselspeicher, der Schreibvorgänge als abgeschlossen meldet, bevor sie es sind — ein Speicherstick, der im Betrieb abgezogen wird, ist ein häufiger Auslöser. Die Datei gehört auf lokalen, ordentlichen Speicher; für gleichzeitige Zugriffe über das Netz ist eine Server-Datenbank das richtige Werkzeug.

Häufige Fragen (FAQ)

?Warum reicht der übliche Abzug mit .dump nicht?

Weil er über die normale SQL-Schnittstelle liest und beim ersten Anzeichen von Beschädigung stehen bleibt. Genau dafür gibt es .recover: Laut Handbuch versucht dieser Befehl, die Datenbank aus den Daten so vieler Seiten wie möglich neu zusammenzusetzen, statt sie regulär zu lesen. Bei einer beschädigten Datei rettet er in der Regel alles, was in den unversehrten Teilen steht, während .dump beim ersten Schaden abbricht. Wer also nur .dump probiert und danach aufgibt, hat womöglich neunundneunzig Prozent seiner Daten weggeworfen, die noch da waren.

?Wie wird eine SQLite-Datei überhaupt beschädigt?

Nicht durch Zufall. SQLite selbst nennt drei Klassiker. Erstens Dateisperren, die nicht halten, was sie versprechen: Enthalten die Sperrfunktionen des Dateisystems Fehler — laut Dokumentation gilt das besonders für Netzdateisysteme und insbesondere NFS — und greifen zwei Prozesse gleichzeitig zu, kann die Datenbank beschädigt werden. Zweitens gelöschte Hilfsdateien: Werden die Journaldateien nach einem Absturz verschoben, gelöscht oder umbenannt, funktioniert die automatische Wiederherstellung nicht mehr. Drittens Datenträger, die beim Schreiben lügen — SQLite nennt USB-Speichersticks in dieser Hinsicht besonders heimtückisch.

?Die Integritätsprüfung meldet ok — ist damit alles gut?

Sie sagt genau das, was sie prüft, und nicht mehr. Laut Handbuch führt PRAGMA integrity_check eine Formatierungs- und Konsistenzprüfung auf niedriger Ebene durch und sucht unter anderem nach Einträgen außerhalb der Reihenfolge, missgebildeten Datensätzen, fehlenden Seiten, fehlenden oder überzähligen Indexeinträgen sowie Bereichen der Datei, die doppelt oder gar nicht benutzt werden. Findet sie nichts, liefert sie eine einzige Zeile mit dem Wert ok. Über die fachliche Richtigkeit der Daten sagt das nichts: Eine strukturell einwandfreie Datenbank kann trotzdem den falschen Kontostand enthalten.

Belege

Diese Seite ist gegen die folgenden Primärquellen geprüft – Hersteller, Standard oder Gesetzestext. Wer es nicht glaubt, muss es nicht: Da steht, wo es nachzulesen ist.

Zuletzt geprüft am . Dokumentation altert – ein Datum daneben ist der einzige ehrliche Umgang damit.

Auch zu finden unter

Verwandte Fehler

SWLästigdatabase is locked

SQLite: database is locked

SQLite meldet „database is locked“? Sie erlaubt nur einen Schreiber — ein hängender Zugriff oder ein Netzlaufwerk bringt sie ins Stocken.

SWSystemzerstörend

Die Sicherung wurde nie zurückgespielt

Eine Sicherung, die niemand je wiederhergestellt hat, ist eine Hoffnung. Das BSI verlangt den Test ausdrücklich – so führt man ihn durch.