Das Symptom
Eine Anwendung, die auf SQLite setzt, bricht sporadisch mit database is locked ab
— mal beim Speichern, mal bei einem Hintergrundvorgang. Unter geringer Last läuft
alles, aber sobald mehrere Zugriffe zusammenkommen oder ein zweiter Prozess mitschreibt,
häufen sich die Sperren.
Die „Layer 8“-Wahrheit
SQLite ist bewusst schlank: keine Serversoftware, nur eine Datei. Dieser Charme hat
eine klare Grenze — beim Schreiben darf zu jedem Zeitpunkt nur ein einziger Vorgang
ran. Lesen können viele gleichzeitig, aber sobald zwei zur selben Zeit schreiben
wollen, muss einer warten, und wartet er zu lange, kommt „database is locked“. Der
Fehler ist also kein Zeichen von Kaputtheit, sondern die eingebaute Regel, die
verhindert, dass sich zwei Schreiber die Datei zerreißen.
Die häufigste vermeidbare Ursache ist ein Vorgang, der die Sperre nicht wieder
loslässt — eine Transaktion, die offen blieb, oder ein abgestürzter Prozess, der sie
mit ins Grab nahm. Kurze, sauber abgeschlossene Transaktionen entschärfen das schon
weitgehend, und der WAL-Modus nimmt Lesern und Schreibern viel Reibung. Der eine
Fehler, den man nie machen sollte: eine SQLite-Datei auf einem Netzlaufwerk betreiben
— dort funktioniert die Sperre grundsätzlich unzuverlässig, und dann ist eine echte
Server-Datenbank ohnehin das passendere Werkzeug.
Die echte, verifizierte Lösung
1000 % faktenbasiert. Jeder Befehl ist real, jeder Pfad existiert. Schritt für Schritt:
1.Das Ein-Schreiber-Prinzip verstehen
SQLite ist eine Datei-Datenbank ohne Server. Sie erlaubt beliebig viele gleichzeitige Leser, aber immer nur einen Schreiber. Will ein zweiter Vorgang schreiben, während der erste die Sperre hält, meldet SQLite „database is locked“. Das ist kein Defekt, sondern das Schutzprinzip.
2.Hängende Verbindungen finden
Oft hält ein Prozess die Sperre, weil er eine Transaktion offen ließ oder abgestürzt ist, ohne sie zu schließen. Prüfen, welche Prozesse die Datenbankdatei geöffnet haben, und einen hängenden gezielt beenden:
fuser meine.db
3.Transaktionen kurz halten und sauber schließen
Im Code jede schreibende Transaktion so kurz wie möglich halten und zuverlässig abschließen (commit) oder zurückrollen. Eine offen vergessene Transaktion blockiert alle anderen Schreiber, bis sie beendet ist.
4.Den WAL-Modus aktivieren
Der Write-Ahead-Logging-Modus erlaubt Lesern und einem Schreiber, sich weit weniger in die Quere zu kommen. Für Anwendungen mit vielen gleichzeitigen Zugriffen deutlich entspannter:
PRAGMA journal_mode=WAL;
5.Niemals über ein Netzlaufwerk betreiben
Liegt die SQLite-Datei auf einer Netzfreigabe, funktioniert die Sperrmechanik unzuverlässig und „database is locked“ tritt sprunghaft auf. Die Datenbank gehört auf ein lokales Laufwerk — für den Netzwerkbetrieb ist eine Server-Datenbank die richtige Wahl.