SQLite mit zwei Python-Prozessen, die darauf zugreifen: ein Lesen, ein Schreiben

22

Ich entwickle ein kleines System mit zwei Komponenten: Eine Komponente fragt Daten von einer Internetressource ab und übersetzt sie in SQL-Daten, um sie lokal beizubehalten. Die zweite liest die SQL-Daten aus der lokalen Instanz und stellt sie über JSON und eine API zur Verfügung.

Ursprünglich plante ich, die Daten mit postgresql beizubehalten. Da die Anwendung jedoch nur ein sehr geringes Datenvolumen zum Speichern und Bereitstellen des Datenverkehrs hat, hielt ich das für übertrieben. Ist SQLite der Aufgabe gewachsen? Ich mag die Idee des geringen Platzbedarfs und die Tatsache, dass für diese eine Aufgabe kein weiterer SQL-Server gewartet werden muss, sehr, aber ich mache mir Sorgen um die Parallelität.

Es scheint, dass bei aktivierter Vorausschreibeprotokollierung das gleichzeitige Lesen und Schreiben einer SQLite-Datenbank erfolgen kann, ohne dass ein Prozess aus der Datenbank gesperrt wird.

Kann eine einzelne SQLite-Instanz zwei gleichzeitig auf sie zugreifende Prozesse unterstützen, wenn nur einer liest und der andere schreibt? Ich habe angefangen, den Code zu schreiben, habe mich aber gefragt, ob dies eine fehlerhafte Anwendung von SQLite ist.

bb
quelle
3
@gnat Cool. Kann eine einzelne SQLite-Instanz zwei gleichzeitig auf sie zugreifende Prozesse unterstützen, wenn nur einer liest und der andere schreibt? Ich habe angefangen, den Code zu schreiben, habe mich aber gefragt, ob dies eine fehlerhafte Anwendung von SQLite ist.
BB
Nur ein Kopf hoch. In meiner vorherigen Firma haben wir SQL (sowohl MS als auch Oracle Express) für einige Speicher verwendet, und wir hatten immer das Gefühl, dass wir mit dem Wenig, das wir gespeichert haben, keine vollständige Datenbank benötigen. In einer der Veröffentlichungen haben wir uns entschlossen, genau das zu tun, was Sie tun. Ersetzen Sie diese Produkte durch SQLite. Wir hatten genau das Gleiche, einen Schreiber, der Daten auf der Festplatte ablegt und das SQL-basierte Inhaltsverzeichnis und den Leseprozess (mehrere Threads) aktualisiert, der das Inhaltsverzeichnis liest, um zu bestimmen, welche Daten abgerufen werden sollen. Ich weiß nicht, was SQLite heutzutage ist, aber die geringe Nebenläufigkeit, mit der wir
konfrontiert
... der Hintern. Ich erinnere mich nicht an alle Details, aber ich denke, wenn ein Prozess versuchte, eine Sperre zu bekommen und es nicht konnte, weil ein anderer las, schlief er für etwas Verrücktes wie 20-30 Sekunden. Am Ende haben wir einen dedizierten Thread erstellt, der für den SQLite-Zugriff verantwortlich war, und dann haben sowohl unsere Prozesse als auch alle Threads in ihnen ihre DB-Anforderungen für diesen einen Thread serialisiert. Im Nachhinein wäre ich wahrscheinlich nicht mehr mit SQLite gefahren.
DXM
1
@DXM danke für die Warnung, aber nach ein paar Tests bin ich auf nichts Ähnliches gestoßen. Ich weiß, dass sqlite mit Version 3 eine grundlegende Überarbeitung erfahren hat, die um 2004 herum erfolgte. Daher frage ich mich, ob Ihre negativen Erfahrungen vor dieser Zeit liegen.
BB
1
... Sie selbst, anstatt sich auf die Sperrschemata von SQLite zu verlassen. Ich habe die Arbeit nicht selbst gemacht, es war ein anderes Team, aber ich habe mich immer auf dem Laufenden gehalten, um Feedback zu geben und aus Neugierde. Ich ging auch online und las unabhängig und fand die Seite des ursprünglichen Autors. Als ich das gelesen habe, hatte ich den Eindruck, dass der Erfinder von SQLite Threads einfach hasste und nicht wusste, warum sie von irgendjemandem verwendet wurden. als nachträglicher Einfall, weil zu viele Leute danach fragten.
DXM

Antworten:

25

Sie suchen nach der Dokumentation zu File Locking And Concurrency .

SQLite-Prozesse verwenden eine Reihe von Sperren, um die Parallelität zu behandeln. Zum Lesen können mehrere Prozesse eine SHAREDSperre erhalten.

Ein schreibender Prozess muss eine RESERVEDSperre erhalten, und nur wenn tatsächlich Änderungen auf die Festplatte geschrieben werden müssen, wechselt er in den PENDINGStatus. Jeder Lesevorgang muss dann die Datei entsperren, woraufhin der Schreibvorgang EXCLUSIVEzum Schreiben in die eigentliche Datenbankdatei verschoben werden kann.

Da der Writer-Prozess nur die Datenbankdatei für tatsächliche Schreibvorgänge (Speicherlöschvorgänge, Festschreibungen) sperren muss, ist eine Einrichtung mit nur einem Reader und nur einem Writer recht gut. Ich würde erwarten, dass es genauso gut, wenn nicht sogar besser ist, als ein Setup mit nur einem Prozess, der das Lesen und Schreiben übernimmt.

SQLite ist weniger geeignet, wenn mehrere Prozesse häufig in dieselbe Datenbank schreiben, da für das Schreiben die exklusive PENDINGSperre zum Serialisieren von Änderungen benötigt wird.

Martijn Pieters
quelle
Danke für die gründliche Antwort Martijn! Ich habe ein paar Skripte zum Testen und es scheint, dass zwei Prozesse eine einzelne SQLite-Instanz gleichzeitig lesen und schreiben können. Ich habe gleichzeitige Lese- und Schreibanforderungen ausgeführt, die alle 1 / 100stel einer Sekunde ausgelöst wurden, und habe immer noch keine gesperrte db-Ausnahme erhalten. Seltsamerweise war das einzige Mal, dass ich eine "Datenbank gesperrt" -Fehlermeldung erhielt, als ich manuell versuchte (mit dem sqlite3-Befehlszeilenclient), einige Zeilen zu löschen, während Leseanforderungen von meinem Skript in 1/100 Sekunde ausgelöst wurden. Ich frage mich, ob pysql nach einem solchen Fehler automatisch einen Schreibvorgang wiederholt.
BB
10

Ich wollte nur nachfassen und allen mitteilen, dass die Implementierung erfolgreich war. Die Arbeit mit SQLite war ein echtes Vergnügen, und mit nur einem Prozess, der es gleichzeitig schrieb, hatten wir nie Probleme mit der Sperrung ... selbst bei sehr schnellen gleichzeitigen Lesevorgängen von einem sekundären Prozess.

bb
quelle