Zum Inhalt springen
myvpsguide

SQLite im echten Betrieb: wann es reicht und worauf es ankommt

Warum SQLite für viele Dienste genug ist, die drei Einstellungen, die man setzen sollte, wie man eine laufende Datenbank sicher sichert und wo die Grenzen wirklich liegen.

veröffentlicht 19.09.2026
4 min lesezeit
fortgeschritten

SQLite hat den Ruf einer Datenbank für Tests und Prototypen. Das ist unfair: Es ist eine der am gründlichsten getesteten Programmbibliotheken überhaupt und steckt in fast jedem Telefon und Browser. Viele selbst gehostete Dienste (Vaultwarden, Uptime Kuma, Gitea und Forgejo für kleine Installationen) nutzen es standardmäßig. Die Frage ist nicht, ob SQLite taugt, sondern ob es zu deinem Zugriffsmuster passt, und ob du es richtig einstellst und sicherst.

Wann SQLite reicht#

Passt gutPasst schlecht
eine Anwendung, ein Servermehrere Server schreiben in dieselbe Datenbank
viel lesen, moderat schreibenviele gleichzeitige Schreibvorgänge von vielen Prozessen
Datenbank auf lokaler PlatteDatenbank auf einem Netzlaufwerk (NFS, SMB)
wenig Betriebsaufwand gewünschtRechte je Benutzer, Replikation, Verbindungen übers Netz

Die wichtigste Eigenschaft: Es schreibt immer nur einer. Lesen können viele gleichzeitig, Schreiben geschieht nacheinander. Für eine Anwendung mit einigen Schreibvorgängen pro Sekunde ist das kein Problem, für eine stark beschriebene Datenbank mit vielen gleichzeitigen Nutzern schon. Dann ist PostgreSQL oder MariaDB die bessere Wahl.

Die drei Einstellungen#

WAL-Modus#

PRAGMA journal_mode = WAL;

Im WAL-Modus („Write-Ahead Log“) schreibt SQLite Änderungen zuerst in eine eigene Datei neben der Datenbank. Leser werden dadurch nicht mehr von Schreibern blockiert. Für fast jeden Serverbetrieb ist das die richtige Einstellung. Sie wird in der Datenbankdatei gespeichert und gilt danach dauerhaft.

Neben datenbank.db liegen dann zwei weitere Dateien: datenbank.db-wal und datenbank.db-shm. Sie gehören dazu. Wer nur die .db kopiert oder die anderen löscht, verliert die jüngsten Änderungen.

Wartezeit bei Sperren#

PRAGMA busy_timeout = 5000;

Ohne diese Einstellung bekommt ein Prozess, der schreiben will, während ein anderer schreibt, sofort den Fehler „database is locked“. Mit ihr wartet er bis zu fünf Sekunden. Sie gilt je Verbindung und muss von der Anwendung beim Öffnen gesetzt werden; viele Programme tun das bereits.

Fremdschlüssel#

PRAGMA foreign_keys = ON;

Aus Kompatibilitätsgründen prüft SQLite Fremdschlüssel standardmäßig nicht. Wer im Schema Beziehungen definiert, erwartet aber meist, dass sie gelten. Auch diese Einstellung gilt je Verbindung.

Sichern, ohne die Datenbank zu beschädigen#

Eine laufende SQLite-Datenbank mit cp zu kopieren, kann eine unbrauchbare Kopie erzeugen, wenn währenddessen geschrieben wird. Es gibt zwei sichere Wege.

Mit dem SQLite-Werkzeug:

sqlite3 /srv/app/daten.db ".backup '/srv/sicherung/daten-$(date +%F).db'"

.backup erzeugt eine in sich stimmige Kopie, auch während die Anwendung weiterläuft.

Oder mit VACUUM INTO:

sqlite3 /srv/app/daten.db "VACUUM INTO '/srv/sicherung/daten-$(date +%F).db'"

Das Ergebnis ist zusätzlich kompakt, weil freie Seiten wegfallen.

Die Kopie ist eine einzelne, vollständige Datei und kann direkt weiter in die verschlüsselte Sicherung, etwa mit Restic. Das Kommandozeilenwerkzeug installierst du unter Debian mit apt install sqlite3.

Bei Docker: im Container oder von außen?

Viele Images bringen sqlite3 nicht mit. Du kannst die Datenbank auch von außen sichern, über das eingehängte Volume, solange sqlite3 auf dem Host installiert ist. Das funktioniert, weil SQLite die Sperren über das Dateisystem regelt und Host und Container dieselbe Datei sehen.

Fortlaufend sichern mit Litestream#

Eine nächtliche Kopie heißt: Im schlimmsten Fall ist ein Tag weg. Litestream läuft neben der Anwendung, liest die WAL-Datei mit und schickt jede Änderung fast sofort an einen Speicher, etwa S3-kompatiblen Objektspeicher oder einen anderen Server per SFTP. Wiederherstellen lässt sich damit auf wenige Sekunden genau. Für einen Dienst, bei dem ein verlorener Tag wehtut, ist das eine günstige Absicherung.

Prüfen und pflegen#

sqlite3 daten.db "PRAGMA integrity_check;"     # sollte „ok" ausgeben
sqlite3 daten.db "PRAGMA quick_check;"         # schneller, für regelmäßige Prüfung
sqlite3 daten.db "VACUUM;"                     # gibt Platz frei, sperrt währenddessen

integrity_check gehört nach einem Absturz oder vor einem Umzug einmal ausgeführt. VACUUM lohnt, wenn viel gelöscht wurde. Es schreibt die Datenbank komplett neu und sperrt sie dabei, also nicht zur Hauptlast ausführen.

Die Grenzen, ehrlich#

  • Kein Netzlaufwerk. SQLite verlässt sich auf Dateisperren, die auf NFS und SMB nicht zuverlässig funktionieren. Die Folge können beschädigte Datenbanken sein.
  • Ein Server. Mehrere Instanzen einer Anwendung auf verschiedenen Rechnern können sich keine SQLite-Datei teilen.
  • Kein Zugriff übers Netz. Es gibt keinen Port, keinen Benutzer, kein Passwort. Wer auf die Datei zugreifen kann, kann alles lesen. Die Dateirechte sind der Zugriffsschutz.

Häufige Fragen#

Wie groß darf eine SQLite-Datenbank werden?#

Technisch sehr groß, weit über das hinaus, was ein VPS an Platte hat. Praktisch begrenzen eher Sicherungsdauer und VACUUM-Laufzeit.

Wie wechsle ich später zu PostgreSQL?#

Viele Anwendungen bringen dafür einen eigenen Migrationsweg mit, Gitea und Forgejo zum Beispiel. Wo nicht, helfen Werkzeuge wie pgloader. Planbar ist das, aber einfacher, wenn man es vorher weiß, siehe Forgejo.

„database is locked“ trotz busy_timeout?#

Dann hält ein Prozess eine Schreibsperre sehr lange, etwa eine offene Transaktion, die nie abgeschlossen wird. fuser daten.db zeigt, welche Prozesse die Datei geöffnet haben.

Ist SQLite schneller als PostgreSQL?#

Für Lesezugriffe aus derselben Anwendung oft ja, weil es keinen Netzweg und keinen eigenen Serverprozess gibt. Bei vielen gleichzeitigen Schreibern nicht. Die Frage ist das Zugriffsmuster, nicht die Datenbank.

Kurz gesagt#

  • SQLite reicht für eine Anwendung auf einem Server mit moderatem Schreibaufkommen.
  • journal_mode=WAL, busy_timeout und foreign_keys=ON setzen.
  • -wal und -shm gehören zur Datenbank; nie löschen.
  • Sichern mit .backup oder VACUUM INTO, nicht mit cp.
  • Kein Netzlaufwerk, kein zweiter Server.
MRMedia

Geschrieben aus dem laufenden Betrieb: MRMedia betreibt eigene Proxmox- Hosts, einen Backup-Server und Kundendienste in der EU. Fehler in einer Anleitung sind Fehler im eigenen Betrieb. Korrekturen bitte über Discord.