Wie sollte man die Korrektheit sicherstellen, wenn mehrere Prozesse auf eine einzelne SQLite-Datenbankdatei zugreifen?SQLite3 und mehrere Prozesse
Antwort
Vermeiden Sie zunächst den gleichzeitigen Zugriff auf SQLite-Datenbankdateien. Parallelität ist einer der Schwachpunkte von SQLite. Wenn Sie eine sehr gleichzeitige Anwendung haben, sollten Sie eine andere Datenbank-Engine verwenden.
Wenn Sie nicht Gleichzeitigkeit vermeiden können oder SQLite fallen, wickeln Sie Ihre Schreib Transaktionen in BEGIN IMMEDIATE;
... END;
. Der Standardtransaktionsmodus in sqlite ist DEFERRED
, was bedeutet, dass eine Sperre nur beim ersten tatsächlichen Schreibversuch erfasst wird. Mit IMMEDIATE
Transaktionen wird das Schloss sofort erworben, oder Sie erhalten sofort SQLITE_BUSY
. Wenn jemand eine Sperre für die Datenbank hält, führen andere Sperrversuche zu SQLITE_BUSY
.
Der Umgang mit SQLITE_BUSY
ist etwas, das Sie für sich selbst entscheiden müssen. Bei vielen Anwendungen funktioniert das Warten auf ein oder zwei Sekunden und dann ein erneuter Versuch ganz in Ordnung, nach n
fehlgeschlagenen Versuchen aufzugeben. Es gibt sqlite3 API-Helfer, die das einfach machen, z. sqlite3_busy_handler()
und sqlite3_busy_timeout()
aber es kann auch manuell gemacht werden.
Sie können auch die Synchronisierung auf Betriebssystemebene verwenden, um eine Mutex-Sperre für die Datenbank zu erhalten, oder die Inter-Thread-/Interprozess-Messaging auf Betriebssystemebene verwenden, um zu signalisieren, wann ein Thread auf die Datenbank zugreift.
Ich weiß, dass man Transaktionen innerhalb eines Prozesses verwenden muss. Meine Situation besteht jedoch darin, dass ich im Gegensatz zu mehreren Threads mehrere Prozesse gleichzeitig auf dieselbe Datenbank zugreife. Bewerkstelligen SQLite-Transaktionen diese Parallelität?!? –
@Tom: Ja, in der sqlite3 OS-spezifischen Portierungsschicht gibt es Funktionen zum Sperren, die über Prozesse hinweg funktionieren. Siehe http://www.sqlite.org/lockingv3.html für mehr – laalto
DEFERRED bedeutet eigentlich, dass die Datenbank nicht (shared) gesperrt ist, bis sie entweder durch Lesen oder Schreiben nach der BEGIN-Anweisung aufgerufen wird (ja, sie sollte auf der lesen). IMMEDIATE bedeutet, dass die Datenbank unmittelbar nach dem Ausführen von "BEGIN SOFORTÜBERTRAGUNG" gesperrt wird. Siehe http://www.sqlite.org/lang_transaction.html –
Jedes SQLite-Grundelement gibt SQLITE_BUSY zurück, wenn es versucht, auf eine Datenbank zuzugreifen, auf die ein anderer Prozess zur gleichen Zeit zugreift. Sie könnten nach diesem Fehlercode suchen und die Aktion einfach wiederholen.
Alternativ können Sie OS-Synchronisation - Mutex auf MS Windows oder etwas ähnliches auf anderen Betriebssystemen verwenden. Der Prozess wird versuchen, den Mutex zu übernehmen, und wenn jemand anders ihn bereits hält, wird der Prozess blockiert, bis der andere Prozess die Operation beendet und den Mutex freigibt. Es sollte sorgfältig darauf geachtet werden, Fälle zu vermeiden, in denen der Prozess den Mutext erwirbt und ihn dann nie freigibt.
Hmm, bietet SQLite keine Sperren zum Schutz des Zugriffs auf die Datenbankdatei? –
Die SQLite FAQ über genau this
Ich habe diese FAQ gelesen, bevor ich meine Frage hier gepostet habe. Ich hätte das natürlich sagen sollen (das war Lektion Nummer zwei, die ich heute gelernt habe). Ich konnte nicht genau sehen, was sie meinten. Soll ich selbst alle Locking-Sachen behandeln, oder hat SQLite dafür Unterstützung? "Wenn ein Prozess schreiben möchte, muss er die gesamte Datenbankdatei für die Dauer der Aktualisierung sperren. Aber das dauert normalerweise nur ein paar Millisekunden. Andere Prozesse warten nur darauf, dass der Schreiber fertig ist und dann weiter." Es würde einige Anstrengungen erfordern, um dies für mich umzusetzen. –
Es ist nicht nur langweilig, es ist auch fehleranfällig. Und ich hoffe, dass SQLite die nötige Unterstützung hat. In diesem Fall frage ich mich, welche Funktionen ich verwenden soll. Als Nebenbemerkung denke ich, dass die Dokumentation von SQLite etwas zu zurückhaltend ist, wenn es um Beispiele mit Quellcode geht ... –
https://meta.stackexchange.com/questions/225370/your-answer-is-in-an-other- Schloss-wenn-ist-eine-Antwort-nicht-eine-Antwort –
Grundsätzlich müssen Sie Ihren Datenzugriffscode mit den Transaktionen wickeln. Dies wird Ihre Daten konsistent halten. Nichts anderes ist erforderlich.
In SQLite verwenden Sie
BEGIN TRANSACTION
COMMIT TRANSACTION
Paare Ihre Transaktionen zu begrenzen. Setzen Sie Ihren SQL-Code dazwischen, damit er in einer einzigen Transaktion ausgeführt werden kann.
Allerdings, wie vorherige Leute vor mir kommentiert haben - Sie müssen aufmerksam auf Nebenläufigkeit Probleme achten. SQLite kann ziemlich schnell arbeiten, wenn es für den Lesezugriff verwendet wird (mehrere Leser sind nicht blockiert und können gleichzeitig ausgeführt werden).
Allerdings - das Bild ändert sich erheblich, wenn Ihr Code Schreib- und Lesezugriff verschachtelt. Mit SQLite - Ihre gesamte Datenbankdatei wird gesperrt, wenn auch nur ein einziger Writer aktiv ist.
- 1. KyotoCabinet und mehrere Prozesse?
- 2. fork() - mehrere Prozesse und Systemaufrufe
- 3. C++ mehrere Prozesse?
- 4. Mehrere wiederkehrende Prozesse
- 5. Mehrere .NET-Prozesse Speicherbedarf
- 6. Gleichzeitiges Schreiben mit sqlite3
- 7. Otto/EventBus über mehrere Prozesse
- 8. fs.createWriteStream über mehrere Prozesse hinweg
- 9. Docker - R erstellt mehrere Prozesse
- 10. Mehrere Worker-Prozesse in Azure
- 11. Kill mehrere Prozesse in VB?
- 12. MySQL-Prozesse und Verbindungen
- 13. Python Popen, Schließen von Streams und mehrere Prozesse
- 14. Wie steuert/enthält Google Chrome mehrere Prozesse?
- 15. Wie laufen mehrere Tornado-Prozesse/Threads/Frontends?
- 16. Sollte ich Threads oder mehrere Prozesse verwenden?
- 17. Mehrere Prozesse, die auf dieselbe Datei zugreifen
- 18. Django - Johnny Cache für mehrere Prozesse
- 19. Mehrere untergeordnete Prozesse von einem übergeordneten Prozess
- 20. mehrere Prozesse in eine einzige Protokolldatei schreiben
- 21. Mehrere WebBrower-Sitzungen/-Prozesse in einem Fenster
- 22. Mehrere Prozesse starten CUDA Kerne parallel
- 23. Mit Erlang spawnen mehrere externe Prozesse
- 24. Chrome Tabs und Prozesse
- 25. Rohre und Prozesse
- 26. Apache und Sqlite3 Problem
- 27. sqlite3 und cursor.description
- 28. SQLite3 Integer und CURRENT_TIMESTAMP
- 29. NSDate und SQLite3
- 30. SQLite3 und "Kaskade" SELECTION
Zumindest könnten Sie Ihre Frage mit der entsprechenden Programmiersprache markiert haben. –
Yeap, oder geben Sie an, dass Sie einen sprachunabhängigen plattformunabhängigen, alles-agnostischen Ansatz benötigen. – sharptooth
Ich würde versuchen, erneut zu fragen, ohne "mir den Code anzeigen" ... –