SQLite produktiv auf einem VPS betreiben
SQLite passt für viele kleine Apps auf einem VPS. Erfahren Sie, wann WAL, busy_timeout und Litestream helfen und welche Grenzen den Betrieb bremsen.
Wenn SQLite die richtige Produktionsdatenbank auf einem VPS ist
SQLite in der Produktion auf einem VPS zu verwenden, ist für die meisten kleinen Anwendungen die richtige Wahl. Der Grund ist einfach: Ein Prozess auf einer Maschine, der in eine Datei schreibt, benötigt keinen Datenbankserver. Es gibt keinen Daemon, den Sie überwachen müssen, keinen Port, den Sie in der Firewall freigeben müssen, kein Passwort, das Sie regelmäßig ändern müssen, und keine zweite Maschine, die Sie betriebsbereit halten müssen. Eine Abfrage ist ein Funktionsaufruf und kein Netzwerk-Roundtrip. Eine Seite mit vierzig Abfragen verursacht daher vierzig Funktionsaufrufe.
Die Einschränkungen sind klar und real. SQLite erlaubt jeweils nur einen Schreibprozess für die gesamte Datenbankdatei. Außerdem kann die Datei nicht zwischen zwei Maschinen gemeinsam verwendet werden. Für einen einzelnen VPS mit einer einzelnen Anwendung sind beide Einschränkungen unproblematisch. Sobald Sie dieses Modell überschreiten, werden beide Einschränkungen zu einem kritischen Problem. Dieser Leitfaden behandelt die Einstellungen, mit denen SQLite auf einem Server sicher betrieben wird, kontinuierliche Backups mit Litestream und den Punkt, an dem Sie auf eine andere Lösung umsteigen sollten.
Installieren Sie zuerst das Kommandozeilenprogramm. Alle folgenden Befehle wurden unter Ubuntu 24.04 ausgeführt.
sudo apt update
sudo apt install -y sqlite3
sqlite3 --versionDer Befehl gibt eine Version aus, die mit 3. beginnt, gefolgt von einem Build-Datum und einem Source-Hash. Ubuntu 24.04 liefert mit Stand Juli 2026 SQLite 3.45.1 aus. Ihre Anwendung verwendet diese Binärdatei wahrscheinlich nicht: Die meisten Sprachlaufzeiten enthalten eine eigene Kopie der SQLite-Bibliothek, häufig eine neuere Version. Prüfen Sie daher die von Ihrem Datenbanktreiber gemeldete Version, bevor Sie sich auf ein aktuelles Feature verlassen.
Warum der WAL-Modus die erste Änderung ist
Standardmäßig verwendet SQLite ein Rollback-Journal. Bevor eine Seite geändert wird, kopiert SQLite die ursprüngliche Seite in eine -journal-Datei und bearbeitet anschließend die Datenbank direkt. Dafür wird die gesamte Datei sicherheitshalber exklusiv gesperrt. Daher wartet jeder Lesevorgang, solange ein Schreibvorgang läuft. Auf einem Laptop fällt das nicht auf. Auf einem Webserver hält ein langsamer Schreibvorgang jede Anfrage auf, die auf die Datenbank zugreift.
Der WAL-Modus (Write-Ahead-Log) kehrt diese Reihenfolge um. Ein Schreibvorgang hängt die neuen Seiten an eine separate -wal-Datei an und lässt die Hauptdatenbank unverändert. Leser greifen weiterhin auf die Hauptdatei in dem Snapshot zu, mit dem sie begonnen haben. Dadurch blockieren Leser den Schreibvorgang nicht, und der Schreibvorgang blockiert die Leser nicht. Später kopiert ein Checkpoint die angesammelten WAL-Seiten zurück in die Hauptdatenbank. Diese eine Änderung trägt wesentlich dazu bei, dass SQLite hinter einer Webanwendung verwendet werden kann.
WAL-Modus aktivieren und bestätigen, dass er bestehen bleibt
mkdir -p ~/app
sqlite3 ~/app/app.db "PRAGMA journal_mode=WAL;"Der Befehl gibt wal aus. Diese Ausgabe ist nicht nur Dekoration. PRAGMA journal_mode gibt den Modus zurück, in dem sich die Datenbank tatsächlich befindet. Eine Antwort mit delete bedeutet daher, dass die Änderung fehlgeschlagen ist und weiterhin das Rollback-Journal verwendet wird.
Der WAL-Modus bleibt dauerhaft aktiviert. Er ist ein Flag im Datenbank-Header und keine verbindungsspezifische Einstellung. Deshalb führen Sie den Befehl einmal pro Datenbankdatei aus. Jede spätere Verbindung übernimmt diese Einstellung, auch nach einem Reboot. Überprüfen Sie das mit einer neuen Verbindung.
sqlite3 ~/app/app.db "PRAGMA journal_mode;"Erstellen Sie jetzt eine Tabelle und prüfen Sie, welche Dateien auf der Festplatte erscheinen.
sqlite3 ~/app/app.db <<'SQL'
CREATE TABLE IF NOT EXISTS notes (id INTEGER PRIMARY KEY, body TEXT NOT NULL);
INSERT INTO notes (body) VALUES ('first row');
SQL
ls -l ~/app/Jetzt gibt es drei Dateien: app.db, app.db-wal und app.db-shm. Die Datei -wal enthält bereits bestätigte Seiten, für die noch kein Checkpoint ausgeführt wurde. Die Datei -shm ist ein gemeinsam genutzter Speicherindex, den jede Verbindung einbindet, damit alle Verbindungen denselben Inhalt des WAL kennen. Beide Dateien gehören zur Datenbank und sind keine temporären Dateien. Wenn Sie während des laufenden Anwendungsbetriebs nur app.db kopieren, fehlen in der Kopie alle aktuellen Commits. Wenn Sie app.db löschen und die beiden anderen Dateien beibehalten, wendet SQLite diese veralteten WAL-Seiten auf jede neue Datei an, die unter diesem Namen erstellt wird. Auf diese Weise beschädigen Benutzer eine neue Datenbank, wenn sie eine Datenbank zurücksetzen möchten.
Die Verbindungseinstellungen, die jede Produktionsanwendung benötigt
Nur journal_mode wird in der Datenbank gespeichert. Jede andere Einstellung unten gilt pro Verbindung. Ihre Anwendung muss sie daher für jede geöffnete Verbindung setzen, einschließlich jeder Verbindung, die ein Pool im Hintergrund erstellt.
PRAGMA journal_mode = WAL;
PRAGMA busy_timeout = 5000;
PRAGMA synchronous = NORMAL;
PRAGMA foreign_keys = ON;busy_timeout = 5000 weist SQLite an, bei einer gesperrten Datenbank bis zu 5000 Millisekunden lang neue Versuche zu unternehmen, bevor database is locked zurückgegeben wird. Der Standardwert ist 0. Daher schlägt SQLite standardmäßig sofort fehl, sobald sich erstmals zwei Schreibvorgänge überschneiden. Das Setzen dieses einzelnen Werts beseitigt die meisten Sperrfehler, die SQLite selbst zugeschrieben werden.
synchronous = NORMAL ist im WAL-Modus die richtige Einstellung. Der Kompromiss muss jedoch verstanden werden. Bei FULL ruft SQLite bei jedem Commit fsync für das WAL auf. Bei NORMAL wird stattdessen bei Checkpoints synchronisiert. Die SQLite-Dokumentation beschreibt den Verzicht eindeutig: Transaktionen sind nach einem Stromausfall oder einem harten Reset nicht mehr dauerhaft gespeichert. Die Datenbank kann durch diesen Stromausfall nicht beschädigt werden. Sie verlieren lediglich die letzten Commits, die noch nicht auf die Festplatte geschrieben wurden. Auf einem VPS ist das normalerweise der richtige Kompromiss, weil dadurch ein fsync aus dem Pfad jedes einzelnen Schreibvorgangs entfernt wird.
foreign_keys = ON ist aus Gründen der Abwärtskompatibilität standardmäßig deaktiviert und gilt pro Verbindung. Ein Schema mit zahlreichen REFERENCES-Klauseln erzwingt keinerlei Integritätsregeln, solange nicht jede Verbindung diese Einstellung aktiviert.
Eine weitere Einstellung wird erst später relevant. SQLite führt automatisch einen Checkpoint aus, sobald das WAL auf mehr als 1000 Seiten anwächst. Die Arbeit übernimmt die Verbindung, die zu diesem Zeitpunkt gerade eine Transaktion abschließt. Für sich genommen ist das unproblematisch. Wenn Litestream ausgeführt wird, stellt sich jedoch die Frage nach dem Zeitpunkt, weil Litestream die Kontrolle über die Checkpoints behalten muss.
Warum database is locked weiterhin auftritt, nachdem Sie busy_timeout gesetzt haben
Dies ist der Fehler, der viele wieder zu Postgres führt. Er hat eine konkrete Ursache.
Ein busy_timeout installiert einen Busy-Handler. SQLite garantiert jedoch nicht, dass dieser aufgerufen wird.
Wenn SQLite feststellt, dass der Aufruf des Busy-Handlers zu einem Deadlock führen könnte, gibt es stattdessen SQLITE_BUSY an die Anwendung zurück.
Der vermiedene Deadlock tritt bei einer Hochstufung der Transaktion auf. Ein alleinstehendes BEGIN bedeutet in SQLite BEGIN DEFERRED. Wenn die erste Anweisung danach ein SELECT ist, befinden Sie sich in einer Lesetransaktion. Wenn ein späteres UPDATE in derselben Transaktion zu einer Schreibtransaktion werden muss und eine andere Verbindung seit Beginn Ihres Lesevorgangs geschrieben hat, kann SQLite Sie nicht warten lassen. Ihr Snapshot ist bereits veraltet. Das Warten würde lediglich zu einem Deadlock zwischen den beiden Verbindungen führen. Die Dokumentation beschreibt das Ergebnis direkt:
Nachfolgende Schreibanweisungen stufen die Transaktion zu einer Schreibtransaktion hoch, wenn dies möglich ist. Andernfalls wird SQLITE_BUSY zurückgegeben.
Ihr Timeout von 5000 Millisekunden wird überhaupt nicht berücksichtigt. Der Fehler tritt sofort auf. Deshalb wirkt es, als hätte die Einstellung keine Wirkung.
Die Lösung besteht aus einem Wort.
BEGIN IMMEDIATE;
UPDATE notes SET body = 'edited' WHERE id = 1;
COMMIT;BEGIN IMMEDIATE übernimmt die Schreibsperre am Anfang, bevor etwas gelesen wird. Es gibt keine Hochstufung. Daher muss kein Deadlock vermieden werden. Der Busy-Handler wird angewendet, und die Verbindung wartet, bis sie an der Reihe ist, statt sofort fehlschlägt. Lassen Sie schreibgeschützte Transaktionen weiterhin verzögert beginnen. Jede Transaktion, die einen Schreibvorgang enthält, sollte sofort beginnen.
Die zweite Ursache für Sperrfehler ist schwerer zu erkennen: eine offene Schreibtransaktion während langsamer Vorgänge. SQLite serialisiert Schreibvorgänge. Eine Transaktion, die geöffnet wird, eine externe API über das Netzwerk aufruft und anschließend einen Commit ausführt, blockiert daher während dieses gesamten Aufrufs alle anderen Schreibvorgänge. Lesen Sie die benötigten Daten, schließen Sie die Transaktion, führen Sie den langsamen Vorgang aus und öffnen Sie anschließend eine kurze Schreibtransaktion, um das Ergebnis zu speichern.
Kontinuierliche Sicherung mit Litestream
Eine nächtliche Kopie kann Schreibvorgänge von bis zu einem Tag verlieren. Wenn Sie cp gegen eine laufende SQLite-Datenbank ausführen, kann außerdem eine Kopie entstehen, die sich nicht öffnen lässt. Zwei Verfahren sind sicher. sqlite3 app.db ".backup /path/to/backup.db" verwendet die Online-Backup-Schnittstelle von SQLite und funktioniert auch mit einer verwendeten Datenbank. Litestream geht weiter: Es überwacht das WAL und überträgt Änderungen kontinuierlich in den Objektspeicher. Dadurch sinkt der Datenverlust im schlimmsten Fall von einem Tag auf etwa eine Sekunde.
Litestream ist eine einzelne Go-Binärdatei, die neben Ihrer Anwendung läuft. Sie sitzt nicht zwischen der Anwendung und der Datenbank. Ihre Anwendung schreibt weiterhin wie bisher in SQLite. Litestream liest das WAL und lädt die geänderten Daten hoch.
cd /tmp
curl -fsSL -O https://github.com/benbjohnson/litestream/releases/download/v0.5.14/litestream-0.5.14-linux-x86_64.deb
sudo dpkg -i litestream-0.5.14-linux-x86_64.deb
litestream versionv0.5.14 ist die Version, die auf der offiziellen Linux-Installationsseite im Juli 2026 dokumentiert ist. v0.5.15 folgte am 21. Juli 2026. Ändern Sie die Version in beiden Zeilen so, dass sie dem aktuellen Tag auf der Releases-Seite entspricht. Wenn Ihr VPS auf arm64 läuft, verwenden Sie stattdessen das passende arm64-Paket.
Die Konfigurationsdatei liegt unter /etc/litestream.yml. Beginnen Sie mit einer lokalen Dateireplikation. Damit prüfen Sie den gesamten Ablauf, ohne Cloud-Anmeldedaten zu benötigen.
dbs:
- path: /home/appuser/app/app.db
replica:
type: file
path: /var/backups/litestream/appBeachten Sie, dass das Feld replica im Singular steht. Litestream 0.5 ersetzte das replicas-Array aus der 0.3-Serie durch einen einzelnen Replikatblock. Eine Konfiguration mit zwei Einträgen schlägt beim Start nun fehl. Viele Anleitungen von Drittanbietern zeigen noch das alte Array. Übernehmen Sie daher die obige Struktur und nicht das erste Suchergebnis. In der 0.5-Serie wurde außerdem das Unterkommando litestream wal in litestream ltx umbenannt, weil sich das Backup-Format auf dem Datenträger geändert hat.
Prüfen Sie, ob die Konfiguration eingelesen werden kann, bevor Sie etwas aktivieren.
sudo litestream databases -config /etc/litestream.ymlPrüfen Sie anschließend den gesamten Ablauf manuell. Bei dieser Variante wird die Konfigurationsdatei umgangen. Eine Datenbank wird an einen einzelnen Pfad repliziert.
mkdir -p /tmp/replica
litestream replicate ~/app/app.db file:///tmp/replica/appDer Prozess läuft im Vordergrund weiter. Öffnen Sie eine zweite Shell, schreiben Sie eine Zeile und stellen Sie das Replikat in einer neuen Datei wieder her.
sqlite3 ~/app/app.db "INSERT INTO notes (body) VALUES ('written after replication started');"
litestream restore -o /tmp/restored.db file:///tmp/replica/app
sqlite3 /tmp/restored.db "SELECT count(*) FROM notes;"Die Anzahl enthält die neue Zeile. Ist das nicht der Fall, wurde die Änderung noch nicht synchronisiert. Litestream überträgt Änderungen in einem sync-interval, das standardmäßig 1 Sekunde beträgt. Warten Sie daher und führen Sie die Wiederherstellung erneut aus. Diese eine Sekunde ist zugleich Ihr Wiederherstellungspunkt. Bei einem Absturz gehen höchstens die Schreibvorgänge aus dem letzten Synchronisierungsintervall verloren. Keine Konfiguration kann diesen Verlust auf null reduzieren.
Für den produktiven Speicher ersetzen Sie den Replikatblock durch eine S3-URL. Das funktioniert mit Amazon S3 und mit S3-kompatiblem Objektspeicher anderer Anbieter.
dbs:
- path: /home/appuser/app/app.db
replica:
url: s3://your-bucket-name/app
region: us-east-1
snapshot:
interval: 24h
retention: 24hSpeichern Sie die Anmeldedaten nicht in dieser Datei. Litestream liest LITESTREAM_ACCESS_KEY_ID und LITESTREAM_SECRET_ACCESS_KEY aus der Umgebung. Legen Sie die Werte daher in einem systemd-Drop-in ab, das root gehört und den Modus 600 hat.
Die oben gezeigten Snapshot-Werte sind die Standardwerte. Der Standardwert für die Aufbewahrungsdauer führt häufig zu Missverständnissen. Die Aufbewahrungsdauer gibt an, wie lange Litestream Snapshots und die zugehörigen Dateien behält. Sie bestimmt damit auch, wie weit Sie in der Zeit zurück wiederherstellen können. Bei 24 Stunden ist eine fehlerhafte Migration, die Sie am Mittwochmorgen bemerken, anhand des Zustands von Montag bereits nicht mehr wiederherstellbar. Setzen Sie retention: 168h auf eine Woche und kalkulieren Sie den zusätzlichen Speicherbedarf ein.
Testen Sie die Wiederherstellung, bevor Sie sie benötigen
litestream restore -o /tmp/check.db /home/appuser/app/app.db
sqlite3 /tmp/check.db "PRAGMA integrity_check;"
sqlite3 /tmp/check.db "SELECT count(*) FROM notes;"Bei Angabe eines Datenbankpfads sucht litestream restore das passende Replikat in /etc/litestream.yml und lädt es herunter. PRAGMA integrity_check gibt ok für eine intakte Datei aus. Jede andere Ausgabe bedeutet, dass die wiederhergestellte Kopie nicht verwendet werden kann. Führen Sie diesen Test regelmäßig mit einem systemd-Dienst und Timer aus und prüfen Sie die Ausgabe. Solange Sie eine Sicherung nicht mindestens einmal wiederhergestellt haben, wissen Sie nicht, ob sie funktioniert.
Litestream unter systemd ausführen
Das Debian-Paket installiert eine litestream-Unit, die /etc/litestream.yml einliest.
sudo systemctl enable litestream
sudo systemctl start litestream
sudo journalctl -u litestream -fEine erfolgreiche Ausgabe nennt jede Datenbank aus der Konfiguration und bleibt anschließend abgesehen von regelmäßigen Synchronisierungszeilen ruhig. Ein Fehler no such file or directory für Ihren Datenbankpfad bedeutet, dass der Pfad in der Konfiguration falsch ist oder der Prozess ihn nicht lesen kann. Die Unit läuft standardmäßig als root. Das sind mehr Berechtigungen, als dieser Dienst benötigt. Litestream muss sowohl die Datenbank als auch das Verzeichnis, in dem sie liegt, lesen und beschreiben können, weil es mit den -wal- und -shm-Dateien neben Ihrer Datenbank arbeitet. Verwenden Sie daher das Konto, das Ihre Anwendung bereits nutzt.
# /etc/systemd/system/litestream.service.d/override.conf
[Service]
User=appuser
Group=appuserWenden Sie die Änderungen mit sudo systemctl daemon-reload und sudo systemctl restart litestream an. Das Einrichten eines dedizierten Dienstkontos mit den geringsten erforderlichen Berechtigungen dauert nur wenige Minuten. Dadurch läuft ein Backup-Agent und kein zweiter root-Prozess auf dem Server.
Eine Reihenfolge ist wichtig, wenn Sie den Rechner vollständig neu aufbauen. Die Datenbank muss wiederhergestellt werden, bevor die Anwendung startet. litestream restore akzeptiert -if-db-not-exists. Der Befehl beendet sich mit dem Exit-Code 0, wenn die Datei bereits vorhanden ist. Daher kann er bei jedem Boot ausgeführt werden. Fügen Sie ihn als ExecStartPre-Zeile in die Unit Ihrer Anwendung ein. Auf einem neuen VPS wird die Datenbank heruntergeladen, während eine vorhandene Installation nichts unternimmt. litestream replicate verfügt über ein entsprechendes -restore-if-db-not-exists-Flag, falls Sie die Einstellung lieber an einer zentralen Stelle verwalten möchten.
Wo SQLite auf einem VPS an Grenzen stößt
Netzwerkdateisysteme. Das ist die Grenze, die Sie nicht durch Konfiguration umgehen können. Der WAL-Modus erfordert, dass alle Prozesse, die die Datenbank verwenden, einen kleinen Speicherbereich gemeinsam nutzen. Diesen stellt die Datei -shm bereit. Die SQLite-Dokumentation formuliert diese Regel ohne Einschränkung:
Alle Prozesse, die eine Datenbank verwenden, müssen sich auf demselben Hostcomputer befinden; WAL funktioniert nicht über ein Netzwerkdateisystem.
Eine Datenbank auf einem eingebundenen NFS (Network File System) oder einer SMB-Freigabe kann daher beschädigt werden. Kein Pragma verhindert das. Hier wird häufig eine wichtige Unterscheidung übersehen. Ein Netzwerk-Blockgerät, wie es die meisten VPS-Anbieter als zusätzlichen Speicher einbinden, erscheint unter Linux als gewöhnliches Laufwerk mit einem gewöhnlichen Dateisystem. Das ist unproblematisch. Eine eingebundene Dateifreigabe ist dagegen nicht geeignet.
Ein zweiter Anwendungsserver. Keine Einstellung macht diesen Betrieb möglich. Sobald zwei Rechner dieselben Daten bereitstellen müssen, benötigen Sie eine Datenbank, die über das Netzwerk kommuniziert. Treffen Sie diese Entscheidung, solange noch Zeit für die Planung bleibt.
Schreibintensive Workloads. Dass immer nur ein Prozess schreibt, ist eine Eigenschaft des Dateiformats und keine anpassbare Einstellung. Kurze Schreibvorgänge sind effizient, weil jeder Commit an das WAL angehängt wird. Der Durchsatz hängt daher stärker von der Latenz des Datenträgers bei kleinen Schreibvorgängen ab als von der CPU. Unter NVMe im Vergleich zu SATA-SSD-Speicher auf einem VPS wird dieser Unterschied erläutert. Lange Transaktionen sind das eigentliche Problem, weil sie alle anderen Schreibvorgänge hinter sich einreihen.
Analytische Abfragen. SQLite ist ein zeilenorientierter Speicher, der für Transaktionen entwickelt wurde. Ein Dashboard, das hundert Millionen Zeilen durchsucht, ist eine andere Aufgabe für ein anderes Werkzeug. DuckDB im Vergleich zu SQLite für den Serverbetrieb zeigt, wo diese Grenze verläuft.
VACUUM bei der Replikation. Ein vollständiges VACUUM schreibt die gesamte Datenbankdatei neu. Litestream muss sie daher vollständig erneut hochladen. Die Litestream-Dokumentation rät davon ab, den Vorgang während aktiver Replikation direkt auszuführen. Stoppen Sie den Replikator, führen Sie den Vacuum-Vorgang aus, starten Sie ihn anschließend erneut und rechnen Sie mit einem neuen vollständigen Snapshot.
Zwei Replikatoren für eine Datenbank. Führen Sie niemals zwei Litestream-Prozesse für dieselbe Datenbank oder dasselbe Replikationsziel aus. Laut Dokumentation liegt es in Ihrer Verantwortung, dies zu verhindern. Andernfalls entsteht eine Replik, die Sie nicht wiederherstellen können.
Was Litestream nicht abdeckt
Litestream schützt nur die Datenbankdatei. Für alles andere sind weiterhin Sie zuständig. Dazu gehören hochgeladene Dateien, die Anwendungskonfiguration, TLS-Zertifikate (Transport Layer Security) und die Unit-Dateien. Kombinieren Sie Litestream nach einem festen Zeitplan mit verschlüsselten Off-Host-Backups mit restic, damit beide Bereiche abgedeckt sind. Wenn die Maschine neu ist, behandelt die ersten zehn Minuten auf einem neuen VPS die Einrichtung des Benutzerkontos und der Firewall, die in dieser Anleitung vorausgesetzt wird.
FAQ
Ist SQLite für eine Produktionsanwendung ausreichend?
Für eine Anwendung auf einem Server: ja, sofern Sie den WAL-Modus aktivieren, ein Busy-Timeout festlegen und kontinuierliche Backups erstellen. Die relevanten Grenzen sind struktureller Art: Es kann jeweils nur einen Writer geben, und die Anwendung muss auf einem Host laufen. Eine Anwendung, die innerhalb dieser Grenzen bleibt, erhält eine Datenbank ohne Netzwerk-Hop und ohne separaten Prozess, den Sie überwachen müssen. Eine Anwendung, die diese Grenzen überschreitet, benötigt eine Client-Server-Datenbank. Keine Optimierung ändert daran etwas.
Warum erhalte ich nach dem Setzen von busy_timeout weiterhin database is locked?
Weil SQLite den Busy-Handler überspringt, wenn das Warten zu einem Deadlock führen könnte. Eine Transaktion, die mit einem einfachen BEGIN beginnt, ist aufgeschoben: Ein öffnendes SELECT versetzt sie in eine Lesetransaktion, und ein späterer Schreibvorgang muss die Transaktion hochstufen. Wenn eine andere Verbindung zwischenzeitlich geschrieben hat, gibt SQLite sofort SQLITE_BUSY zurück, statt Ihren Busy-Handler aufzurufen, weil Ihr Lese-Snapshot bereits veraltet ist. Starten Sie jede Transaktion, die schreiben soll, mit BEGIN IMMEDIATE. Dadurch wird die Schreibsperre von Anfang an angefordert, und das Timeout greift.
Kann ich meine SQLite-Datenbank auf einem Netzwerkspeicher ablegen?
Nicht auf einem Netzwerkdateisystem wie NFS oder SMB. Der WAL-Modus benötigt den gemeinsamen Speicher aller Prozesse über die Datei -shm. Laut SQLite-Dokumentation müssen sich alle Prozesse, die die Datenbank verwenden, auf demselben Hostcomputer befinden. Ein von Ihrem Provider bereitgestelltes und eingebundenes Netzwerkblockgerät ist etwas anderes: Linux erkennt darin einen normalen Datenträger mit einem normalen Dateisystem, und SQLite funktioniert dort.
Benötige ich Litestream, wenn ich bereits nächtliche Backups ausführe?
Das hängt davon ab, wie viele Daten Sie verlieren können. Ein nächtlicher Job bedeutet, dass bis zu vierundzwanzig Stunden an Schreibvorgängen verloren gehen können. Litestream synchronisiert ungefähr einmal pro Sekunde, sodass ein Absturz ungefähr die Schreibvorgänge der letzten Sekunde kostet. Litestream ist außerdem sicherer als das Kopieren der Datenbankdatei mit cp, weil dabei eine Datenbank während eines Schreibvorgangs erfasst werden kann. Litestream deckt nur die Datenbank ab. Lassen Sie daher zusätzlich ein allgemeines Datei-Backup laufen.