2016-06-30 10 views
1

Ich habe eine einfache Multithread-Anwendung. Alle Threads werden nur Operationen in derselben Datenbank ausführen. Aber bevor ein Thread eine Put-Operation ausführt, wird er zuerst eine Mutex-Sperre erwerben, um die Schlüsselnummer zu erhöhen und dann die Sperre aufzuheben und dann die Put-Operation durchzuführen, dh die Threads werden Elemente mit unterschiedlicher Schlüsselnummer möglicherweise gleichzeitig einfügen Zeit. Das habe ich in meiner Bewerbung gemacht.Multithread-Anwendungen in Berkeley DB

Worüber ich immer noch verwirrt bin ist, ob diese einfache App DB_INIT_LOCK-Flag oder DB_INIT_CDB-Flag angeben muss? Ich habe das Dokument über diese Flaggen gelesen. DB_INIT_CDB bedeutet mehrere Lesevorgänge/einzelner Schreiber, aber in meiner einfachen App können die Threads gleichzeitig arbeiten, nicht einzelne Schreiber, also brauche ich sie nicht. Für DB_INIT_LOCK, da die Threads nie das Element mit dem gleichen Schlüssel einfügen, brauche ich es nicht, habe ich Recht?

Bitte korrigieren Sie mich, wenn ich falsch liege. Danke vielmals.

Antwort

1

Sie geben korrekt an, dass DB_INIT_CDB Ihnen eine Umgebung mit mehreren Lesern und einem Schreiber bietet. Dies versetzt Berkeley DB in eine völlig andere Arbeitsweise. Da Sie jedoch mehr als einen Autor haben, können Sie ihn nicht verwenden.

Sie werden diese beiden Fahnen mindestens benötigen:

DB_INIT_LOCK: Sie Ihre eigene Verriegelung um Ihre Datenbank Schlüsselerzeugung zu tun. Aber wenn Sie Datensätze in die Datenbank einfügen, Berkeley DB wird einige der gleichen Teile des Speichers berühren. Die ersten beiden Datensätze, die Sie einfügen, befinden sich beispielsweise direkt nebeneinander in der Datenbank. Wenn sie nicht groß sind, befinden sie sich auf derselben "Speicherseite" der Datenbank. Sie benötigen dieses Flag, um BDB zu sagen, dass es seine eigene Sperrung durchführen soll.

Es ist das gleiche, als ob Sie Ihren eigenen In-Memory-Binärbaum implementiert hätten, bei dem mehrere Threads geändert wurden. Sie müssen eine Art Sperren verwenden, um zu verhindern, dass die Threads den Baum mit inkompatiblen Updates vollständig zerstören.

DB_THREAD: Dieses Flag zeigt BDB an, dass mehrere Threads die gleiche Datenbankumgebung verwenden.

Möglicherweise müssen Sie Transaktionen verwenden oder zumindest BDB erlauben, sie interaktiv zu verwenden. Das ist DB_INIT_TXN. Und ich brauchte immer DB_INIT_MPOOL und DB_PRIVATE, damit BDB malloc() verwenden kann, um einen Teil seines eigenen Speichers zu verwalten.

(Wenn Sie ein einfaches Inkrement für Ihren Schlüssel haben, sollten Sie eine atomare Inkrementierung statt eines Mutex verwenden. Wenn Sie C mit gcc verwenden, kann das eingebaute __sync_fetch_and_add (oder __sync_add_and_fetch) dies tun Aus C++, können Sie Post-Inkrement von std :: atomic verwenden.)

+0

Vielen Dank für Ihre Antwort. Es ist sehr wahrscheinlich, dass die ersten beiden Datensätze auf der gleichen Seite in db sind. Ich habe jedoch gelesen, dass "die Zugriffsmethoden außer der Warteschlange Sperren auf Seitenebene sind". Hier ist der [link] (http://www.mtholeyoke.edu/~mcrowley/perl-tmp/docs.db277/ref/am/pagesize.html). Wenn ich also die Zugriffsmethode auf Btree eingestellt habe, hilft mir BDB beim automatischen Sperren auf Seitenebene. Ich muss DB_INIT_LOCK in diesem Szenario nicht angeben. – HuangJie

+0

Die Berkeley DB-Dokumentation kann sicher verwirrend sein. Dieser Link ist technisch korrekt - er funktioniert auf Seitenebene. Aber ich kann Ihnen aus Erfahrung sagen, dass es das sicherlich nicht automatisch macht. Sie benötigen DB_INIT_LOCK, um es zu aktivieren. Aber Sie werden es ziemlich schnell herausfinden, wenn Sie die Datenbank mit mehreren Threads ausprobiert haben! :) –