Datenbanken 06.03.2025, 08:10 Uhr

Concurrency-Probleme mit SQLite: Ein Erfahrungsbericht von SkyPilot

Die Nutzung von SQLite für das Management von Zuständen in Cloud-Anwendungen bietet zahlreiche Vorteile, birgt jedoch auch Herausforderungen, insbesondere bei gleichzeitigen Schreibvorgängen. SkyPilot teilt seine Erkenntnisse und Lösungsansätze.
(Quelle: sqlite)
SkyPilot verwendet SQLite für das Management von Zuständen in seinen Anwendungen. SQLite ist bekannt für seine Fähigkeit, Millionen von Abfragen pro Sekunde zu verarbeiten und grosse Datenmengen zu bewältigen. Dennoch ist ein zentrales Problem, das bei der Skalierung der Managed-Jobs-Funktion auftrat, die Begrenzung von SQLite bei gleichzeitigen Schreibvorgängen. In typischen Konfigurationen von SkyPilot läuft das System als CLI-Anwendung auf dem Laptop des Nutzers, was einen Einsatz von SQLite naheliegend macht. Das Team stand vor der Herausforderung, effektive Lösungen für die gleichzeitigen Schreibvorgänge zu finden, die besonders bei mehreren hundert oder sogar tausend Jobs auftraten.
In ihrer Architektur verantwortet eine VM-Instanz oder ein Kubernetes-Pod als Controller die Verwaltung des Zustands von vielen anderen Instanzen, die die Jobs tatsächlich ausführen. Hierbei werden verschiedene Prozesse zur Überwachung und Aktualisierung der Jobs eingesetzt. Bei einer Zunahme von gleichzeitigen Schreibvorgängen trat häufig der Fehler "sqlite3.OperationalError: database is locked" auf. Diese Probleme konnten nur unter sehr spezifischen Bedingungen reproduziert werden, was die Fehlersuche kompliziert machte.
Lösungsidee: Umgehe möglichst Situationen mit vielen gleichzeitigen Schreibvorgängen in SQLite. SQLite verwendet Datenbankniveau-Sperren, die in solchen Szenarien zu Verzögerungen oder einem Verlust von Prozessen führen können. Wenn SQLite unbedingt verwendet werden muss, ins besonders um mit hoher Schreibkonkurrenz umzugehen, sollte der WAL-Modus (Write-Ahead Logging) zusammen mit einer hohen Timeout-Wert-Einstellung genutzt werden.
Die SQLite-Dokumentation macht ausdrücklich darauf aufmerksam, wann es besser ist, zu einem klassischen Client/Server-RDBMS zu wechseln. Für Anwendungen, die eine hohe Parallelität erfordern, wird empfohlen, auf andere Datenbanken wie PostgreSQL oder TiDB umzuschwenken. SkyPilot entschied sich jedoch, an SQLite festzuhalten und die bestehende Architektur weiter zu erschliessen.
Die ersten Schwierigkeitsgrade deuteten darauf hin, dass auch das sichere Erhalten der Datenbank-Sperre eine kritische Rolle spielte. SQLite hat verschiedene Mechanismen zur Sicherstellung der Konsistenz, wobei viele parallele Leser gleichzeitig auf die Datenbank zugreifen können. Für Schreibzugriffe hingegen wird eine exklusive Sperre benötigt. Selbst im WAL-Modus lässt sich nicht verhindern, dass irgendwann eine Sperre entsteht, wenn mehrere Schreibvorgänge gleichzeitig stattfinden.
Die grösste Erkenntnis war jedoch, dass die Fehler mit einer Erhöhung der Timeout-Werte verringert werden konnten. SkyPilot stellte fest, dass durch eine Verdopplung des Timeout-Wertes auch die Wahrscheinlichkeit eines Timeout merklich gesenkt wurde. So wird beispielsweise bei einer sehr hohen Schreibkonkurrenz von 1000 Prozessen empfohlen, die Timeout-Einstellung auf über 20 Sekunden zu erhöhen.
SkyPilot ist ein Framework, das es ermöglicht, KI und Batch jobs laufen zu lassen.



Das könnte Sie auch interessieren