2010-05-05 5 views
7

Wir verwenden SQLite in einer Multi-Prozess- und Multithread-Anwendung. Die SQLite-Datenbankdateien werden mit der eingebetteten SQLite-Verschlüsselung verschlüsselt. Die FAQ besagt, dass SQLite in der Lage sein sollte, mehrere Prozesszugriffe mithilfe von Sperrmechanismen zu verwalten. Wir haben ein seltsames Problem: Wenn viele Threads auf die gleiche Datenbankdatei zugreifen, kommt es manchmal zu Constrains-Verletzungen, genauer - ein Feld mit einem eindeutigen Constrain erhält doppelte Werte nach dem Aufruf der "insert or replace" -Anweisung. Es passiert jetzt ziemlich oft, dass wir die Verschlüsselung verwenden. Bevor wir mit der Verwendung der SQLite-Verschlüsselung begannen, bemerkten wir ein solches Verhalten nicht. Gibt es spezifische Probleme mit diesem Problem?SQLite multi Prozesszugriff

+0

SQLite besagt, dass Sie nicht das gleiche Objekt über Threads teilen können. Bist du sicher, dass du es nicht tust? – Andrey

+0

@Andrey: können Sie den Link zu diesem Eintrag? Wenn ich kürzlich darüber gelesen habe, sagt SQLite, dass es threadsicher ist, obwohl * sie glauben, dass Threads böse sind und dass man SQLite nicht in einem Multithread-Programm verwenden sollte, es sei denn, es wird nur von einem Thread zugegriffen. Aber technisch gesehen sollte es threadsicher sein. Zumindest erinnere ich mich an das Lesen. – Dave

+0

@Dave: http://www.sqlite.org/cvstrac/wiki?p=MultiThreading Stichwort: Mit "threadsafe" meinen wir, dass Sie verschiedene SQLite Datenbankverbindungen in verschiedenen Threads gleichzeitig verwenden können. – Andrey

Antwort

8

Während SQLite ist „thread-safe“ Sie kann immer noch nicht gleichzeitig auf die Datenbank ändern:

Jeder Thread dann eine Anzahl der Datensätze einzufügen geht, sagen wir mal 1000. Das Problem Sie begegnen ist der folgenden: ein Thread wird die Kontrolle über die Datenbank durch Festlegen einer Sperre auf die Datei erhalten. Das ist in Ordnung, aber der Rest der Threads wird für jeden versuchten INSERT weiterhin fehlschlagen, während die Sperre aktiv ist. (reference)

Nur ein Thread erlaubt wird, um die Datenbank zu einem Zeitpunkt, zu ändern, aber Sie können mehrere Threads haben, die Versuch die Datenbank zu ändern.

Wenn Sie die fehlerhafte-while-locked Problem vermeiden, sollten Sie die SQLITE_BUSY Flagge überprüfen:

-Test für SQLITE_BUSY, die ich nicht ursprünglich zu tun haben. Hier einige Pseudo-Code eine Lösung zu veranschaulichen:

while (continueTrying) { 
    retval = sqlite_exec(db, sqlQuery, callback, 0, &msg); 
    switch (retval) { 
     case SQLITE_BUSY: 
     Log("[%s] SQLITE_BUSY: sleeping fow a while...", threadName); 
     sleep a bit... (use something like sleep(), for example) 
     break; 
     case SQLITE_OK: 
     continueTrying = NO; // We're done 
     break; 
     default: 
     Log("[%s] Can't execute \"%s\": %s\n", threadName, sqlQuery, msg); 
     continueTrying = NO; 
     break; 
    } 
    } 

    return retval; 

same reference

Meine Wette ist, dass Ihre Einschränkungsverletzung nichts mit Multithreading zu tun hat, so könnten Sie bitte die tatsächliche Beschränkung verletzt, dass Sie Beiträge verfassen erhalten (oder ein Beispiel, das www.sscce.org entspricht).

0

Stellen Sie sicher, dass Sie keine Verbindungen über Threads teilen - jeder Thread sollte eine eigene Verbindung herstellen. Und stellen Sie sicher, dass Sie Ihre Abfragen in Transaktionen einschließen.

Ich verwende den Open-Source-System.Data.Sqlite (http://sqlite.phxsoftware.com/) ADO.Net-Wrapper, der threadsicher ist, solange Sie keine Verbindungen über Threads teilen. Es verschlüsselt auch leicht die Datenbank, wie hier beschrieben: http://sqlite.phxsoftware.com/forums/t/130.aspx (stellen Sie einfach die Passwort-Eigenschaft ein). Durchsuchen Sie sein Forum, um zu erfahren, wie er die Microsoft Crypto API speziell für die Verschlüsselung und für Details zur Threadsicherheit verwendet.

2

Vielen Dank für Ihre Kommentare!

(es ist zu erwähnen, dass wir die System.Data.SQLite verwenden.Net-Bibliothek)

In der Zwischenzeit haben wir einige weitere Tests und hier sind die Ergebnisse

===============

Wir haben die Tester gebaut haben, dass macht folgendes: - Erstellen Sie eine Tabelle mit einer Anzahl von Feldern. Eines der Felder - nvarchar (255) - hat einen eindeutigen Index: "create unique index IX_MyKey für Tabelle (MyKey)" - Start vieler identischer Prozesse (25) gleichzeitig - Jeder Prozess hat einen Schlüssel (String repräsentiert eine Zahl 1- 25) - Jeder Prozess hat einen einzigen (Haupt-) Thread den folgend in einer Schleife für 30 Sekunden zu tun:

den Datensatz gelesen, wo MyKey = @ MyKey (den Schlüssel des Prozesses) einen Wert einer bekommen numerisches Feld ‚Wert + 1‘ auf dem gleichen Feld des gleichen Datensatzes „einfügen oder ersetzen ... wo MyKey = @ MyKey“ schreiben zurück

===============

  • Wenn wir die System.Data.SQLite Bibliothek ohne Verschlüsselung Sie alle oben mit - alles wie erwartet funktioniert (einschließlich Sperren, die nach unten bremsen der Zugriff auf die Datenbank, wenn die Menge der Prozesse erhöht)

  • wenn wir die Verschlüsselung verwenden (indem Sie ein Passwort für die Datenbank) Einstellung der Index eindeutig constrain ist „gebrochen“ - es erscheint Datensätze, die die gleiche MyKey-Wert

===============

So scheint es das Problem ist irgendwie im Zusammenhang mit der Verschlüsselung ...