Konkurrierendes read/write unter anydbm und shelve

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

Hallo,

die shelve-Doku sagt unter anderem:
"The shelve module does not support concurrent read/write access to shelved objects. (Multiple simultaneous read accesses are safe.) When a program has a shelf open for writing, no other program should have it open for reading or writing. Unix file locking can be used to solve this, but this differs across Unix versions and requires knowledge about the database implementation used."

Nachdem 'shelf.open()' letztlich 'anydbm' bemüht ist es ja wohl so, dass auch 'anydbm' konkurrierende Schreib-/Lesezugriffe nicht unterstützt.
Bleiben für mich die Fragen:
  • Warum keine Lesezugriffe, trotz Anmerkung: (Multiple simultaneous read accesses are safe.) Also was denn nun?
  • Warum nennt sich 'anydbm' dann Datenbankmodul? Ist das Verwalten von konkurrierenden/gleichzeitigen Zugriffen nicht eine elementare Aufgabe jedes Datenbanksystems?
  • Oder besteht zwischen konkurrierend und gleichzeitig ein kleiner aber feiner Unterschied?
mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Das heisst dass du nicht lesen und gleichzeitig schreiben kannst, mehrere parallel Lesevorgänge sind unproblematisch.

Die Verwaltung von solchen Zugriffen ist nicht wirklich elementare Aufgabe eines Datenbanksystems, allerdings würde ich anydbm auch nicht wirklich als Datenbanksystem bezeichenen.
BlackJack

@mutetella: Nicht jedes Datenbanksystem hat überhaupt konkurrierende Zugriffe. Anlegen, schreiben, lesen, und löschen von Daten sind die elementaren Aufgaben — alles darüber hinaus ist Extra. Wenn man das nicht so sieht, schliesst man Klassiker wie dBase vom Begriff Datenbanksystem aus. Das kann es ja wohl nicht sein.
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

Ok. Also muss ich, wenn ich 'anydbm' oder 'shelve' einsetzen möchte, mich um das Sperren der DB während eines Schreibvorganges selbst kümmern?

Wie ist das eigentlich, wenn auf einen Datensatz zugegriffen wird? Ist dieser Datensatz dann für Schreibzugriffe solange gesperrt, bis der Zugriff abgeschlossen ist?
Ich meine, wenn jemand stundenlang an einem Datensatz arbeitet, dann kann das ja zum Problem werden, wenn dieser Datensatz solange nur gelesen werden kann.
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

mutetella hat geschrieben:Ok. Also muss ich, wenn ich 'anydbm' oder 'shelve' einsetzen möchte, mich um das Sperren der DB während eines Schreibvorganges selbst kümmern?
Was nicht so einfach sein dürfte. Dürfen ja keinerlei Race-Conditions auftreten - ich wüsste aus dem Stehgreif nicht, wie man so etwas implementiert.
Wie ist das eigentlich, wenn auf einen Datensatz zugegriffen wird? Ist dieser Datensatz dann für Schreibzugriffe solange gesperrt, bis der Zugriff abgeschlossen ist?
Na, das ist ja grad Sinn der Sache...
Ich meine, wenn jemand stundenlang an einem Datensatz arbeitet, dann kann das ja zum Problem werden, wenn dieser Datensatz solange nur gelesen werden kann.
Sicher. Nur kann man das Problem kaum lösen. Du kannst nur auf höherer Ebene versuchen, eine solche Situation auszuschließen, etwa durch Hinweise / Warnungen an den Verursacher, seine Arbeit zu speichern und freizugeben. So etwas in der Art halt.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
BlackJack

@mutetella: Wenn Du schreiben bei konkurrierenden Zugriffen haben willst, dann musst Du das bei `anydbm` oder `shelve` selbst absichern, ja. Ist nicht ganz trivial wie die Dokumentation schon sagt, weil Du einen Sperrmechanismus finden musst, der auf allen Plattformen, die Du unterstützen möchtest, funktioniert. Oder verschiedene implementieren. Oder eine andere Datenbank verwenden.

Nach dem ersten Absatz fehlt zur Frage der Kontext. Wo wird auf einen Datensatz zugegriffen? `anydbm` sperrt nichts. Wenn Du selbst einen Sperrmechanismus implementierst, bestimmst *Du* das Verhalten, da musst Du Dich also selbst fragen wie das genau funktionieren soll.

Wenn Sperren wichtig sind, würde ich wohl eine andere DB verwenden. Zum Beispiel eine der konkreten Implementierungen von `anydbm`. Die Berkeley DB kennt soweit ich weiss Sperren. Zumindest innerhalb eines Prozesses. Das ist dann ja auch noch mal eine Frage die Du Dir stellen und beantworten musst — soll da von mehreren Prozessen aus gleichzeitig zugegriffen werden.
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

Hyperion hat geschrieben:Was nicht so einfach sein dürfte. Dürfen ja keinerlei Race-Conditions auftreten - ich wüsste aus dem Stehgreif nicht, wie man so etwas implementiert.
Sobald Daten zur potentiellen Änderung herangezogen werden, werden diese in der DB markiert. Sind sie bereits zuvor markiert worden, können sie nicht für eine eventuelle Änderung verwendet werden.
Aber ich vermute, Du meinst was anderes, das mir nicht auffällt... :?
BlackJack hat geschrieben:Zumindest innerhalb eines Prozesses.
Gilt eine Sperre nicht immer für alle Prozesse? Oder was meinst Du damit?
BlackJack hat geschrieben:... soll da von mehreren Prozessen aus gleichzeitig zugegriffen werden.
Weshalb sonst bräuchte es Sperren? Verstehe ich jetzt auch nicht...

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
BlackJack

@mutetella: Ich weiss nicht was Du jetzt unter einer Sperre verstehst, aber wenn ich irgendwo im Programm ein Flag habe was bedeuten soll "Jetzt darf da nicht mehr auf Ressource X zugegriffen werden", dann gilt das natürlich nur in dem Prozess wo dieses Flag gespeichert ist — andere Programme "sehen" diese Speicherstelle ja nicht — und auch nur für Code der das auch abfragt bevor er auf Ressource X zugreift.

Sperren braucht man um das mehrfache verwenden von Ressourcen zu verhindern. Innerhalb eines Prozesses ist das offensichtlich bei Threads nützlich. Aber auch ohne Threads kann man ja "nebenläufigen" Code zum Beispiel mit Hilfe von Ereignisschleifen und haben. Selbst bei ganz "normalem" linearen Code kann es notwendig sein Ressourcen zu schützen.
Benutzeravatar
noisefloor
User
Beiträge: 3843
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

@mutella: Wenn bei deiner Kalender-Applikation Mehrfachzugriff vorkommen könnte _und_ du in der Wahl der DB frei bist (bist du ja scheinbar ;-), dann nimm' am besten ein DB, die dafür ausgelegt ist bzw. die Locks selber setzt. Der einfachheit halber. :-)

Gruß, noisefloor
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

BlackJack hat geschrieben:... andere Programme "sehen" diese Speicherstelle ja nicht ...
Weshalb? Bevor ein Prozess sich daran macht, Daten zu ändern, markiert er das in der Datenbank. Ab diesem Zeitpunkt gilt dieser Datensatz als gesperrt. Sollte also ein anderer Prozess vorhaben, dieselben Daten zu ändern, wird er, weil er ja auch dieses Vorhaben in der Datenbank bekanntmachen möchte, davon unterrichtet, dass ein anderer Prozess bereits am Zuge ist.
BlackJack hat geschrieben:Selbst bei ganz "normalem" linearen Code kann es notwendig sein Ressourcen zu schützen.
Das würde mich interessieren. Hast Du da vielleicht ein Beispiel?
noisefloor hat geschrieben:... dann nimm' am besten ein DB, die dafür ausgelegt ist bzw. die Locks selber setzt. Der einfachheit halber.
Ja, natürlich! Mich interessiert jetzt auch nur, wie man so etwas realisieren könnte und was da alles eine Rolle spielen kann.

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
BlackJack

@mutetella: Ein Flag im Speicher eines Prozesses "sehen" andere Prozesse nicht. Das ist halt so. Ich verstehe jetzt nicht was das damit zu tun hat, dass man das auch in der Datenbank markieren könnte. Das ist ja eine andere Situation. Wobei das *in* der Datenbank eigentlich nur geht, wenn die Datenbank selbst schon einen Sperrmechanismus unterstützt, denn die Aktion "Flag testen und setzen" muss ja atomar sein.

Bei "linearem" Code kann man mit Sperren bestimmte Operationen schützen, zum Beispiel eine Endlosrekursion verhindern, oder Teile von APIs schützen aufgerufen zu werden wenn sich etwas in einem inkonsistenten Zustand befindet.
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

BlackJack hat geschrieben:Ein Flag im Speicher eines Prozesses "sehen" andere Prozesse nicht. Das ist halt so. Ich verstehe jetzt nicht was das damit zu tun hat, dass man das auch in der Datenbank markieren könnte.
Und ich verstehe nicht, weshalb das Flag im Speicher eines Prozesses für andere Prozesse wichtig wäre. Die Markierung in der Datenbank ist doch entscheidend.
BlackJack hat geschrieben:Wobei das *in* der Datenbank eigentlich nur geht, wenn die Datenbank selbst schon einen Sperrmechanismus unterstützt, denn die Aktion "Flag testen und setzen" muss ja atomar sein.
Richtig, das ist ein Problem... :)
Dazu lese ich gerade den Wikipedia-Eintrag zu ACID und die darin enthaltenen Links zu weiterführenden Artikeln. Es müsste doch möglich sein, dem 'shelve'-Modul ACID-Transaktionen zu spendieren...
Ok, aber nicht mehr heute, morgen vielleicht... :)

Jetzt verstehe ich auch, was Du damit gemeint hast, dass alles, das über das Anlegen, Schreiben, Lesen und Löschen von Daten hinausgeht, ein Extra ist...

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
lunar

@mutetella: Du hast BlackJack nicht verstanden. Eine atomare Speicherstelle eines Prozesses ist eben nicht wichtig für andere Prozesse, andere Prozesse sehen diese Speicherstelle ja nicht einmal.

Für Dich als Entwickler aber ist es wichtig, zu wissen, wie die Sperre der Datenbank umgesetzt wird, weil sich daraus direkt ergibt, ob und wie konkurrierende Zugriffe möglich sind. Und es ist halt eben nicht so, wie von Dir behauptet, dass eine Sperre immer für alle Prozesse gilt. Das hängt vielmehr unmittelbar von der Implementierung des Sperrmechanismus ab, und manche Datenbanksysteme wie die von BlackJack als Beispiel erwähnte Berkley Datenbank unterstützen halt keine prozessübergreifenden Sperren.
BlackJack

@lunar: Die Berkeley DB unterstützt prozessübergreifende Sperren.
lunar

@BlackJack: Mag sein ih habe nicht die geringste Ahnung von der Berkley DB. Die Aussage entnahm ich dem letzten Absatz Deines Beitrags :) Danke der Korrektur :)
Antworten