Zwei gleichzeitge schreibzugriffe

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
The Spirit
User
Beiträge: 276
Registriert: Freitag 8. Juni 2007, 08:50
Wohnort: 84xxx Bereich
Kontaktdaten:

Hi.
Wie kann ich es verhindern, das zwei User meiner Datenbank gleichzeit in die selbe Tabelle bei mysql schreiben?
Aktuell setzt der schreibprozess ein flag in einer seperaten tabelle und jeder prozess (egal ob schreiben oder lesen) eines weiteren users sieht erst nach, ob das flag gesetzt ist oder nicht.
Jedoch kann es im ungeünstigen fall dazu kommen, das das flag vom ersten user noch nicht gesetzt ist, und der zweite genau in diesem moment abfrägt, ob das flag gesetzt ist.
Somit würden zwei gleichzeitige schreibprozesse erfolgen, was ich ja nicht will. Die zeitdifferenz muss zwar sehr gering sein, aber durch latencen im netzwerk kann es schon mal vorkommen.
Bietet hier mysql etwas an, um dies zu verhindern?
Thx
Benutzeravatar
Defnull
User
Beiträge: 778
Registriert: Donnerstag 18. Juni 2009, 22:09
Wohnort: Göttingen
Kontaktdaten:

http://dev.mysql.com/doc/refman/5.1/de/ ... mands.html

Aber das hört sich eher nach einem Design-Fehler an.
Bottle: Micro Web Framework + Development Blog
The Spirit
User
Beiträge: 276
Registriert: Freitag 8. Juni 2007, 08:50
Wohnort: 84xxx Bereich
Kontaktdaten:

wie meinst du das mit dem designfehler?
Benutzeravatar
Defnull
User
Beiträge: 778
Registriert: Donnerstag 18. Juni 2009, 22:09
Wohnort: Göttingen
Kontaktdaten:

Normalerweise kann man die meisten Race Conditions durch clevere Herangehensweise umgehen und Table-Locks weitgehend vermeiden. Da gibt es (gerade bei SQL) ein paar Tricks und Patterns für. Beschreib mal dein eigentliches Problem.
Bottle: Micro Web Framework + Development Blog
The Spirit
User
Beiträge: 276
Registriert: Freitag 8. Juni 2007, 08:50
Wohnort: 84xxx Bereich
Kontaktdaten:

ich hab ein prog geschrieben, welche testdaten in eine datenbank schreibt.
dieses prog wird jedoch von mehr leuten im gleichen netwerk verwendet.
startet jetzt einer das prog um neue testdaten in die datenbank zu schreiben schaut das prog nach, ob es die daten schon gibt, und wenn nicht, dann schreibt er die daten in die datenbank.
bevor er jedoch mit dem schreiben beginnt, setzt er in einer nebentabelle ein "ich schreib grad in die datenbank"-bit.
wenn jetzt ein weiterer kollege andere daten in die datenbank schreibt (der schreibprozess dauert schon etwas länger, da die einzelnen datensätze recht groß sind) überprüft das programm erstmal, ob das "ich schreib grad in die datenbank"-bit gesetzt ist. ist dies der fall sagt es dem user, ich kann grad nicht reinschreiben und das wars.
somit kann es eigentlich nie vorkommen, das zwei user, gleichzeitig in die datenbank schreiben.
ist jetzt der erste user mit dem schreiben fertig, wird das "ich schreib grad in die datenbank"-bit wieder zurückgesetzt und es kann jetzt wieder jeder user in die datenbank schreiben.
was ist aber, wenn das schreiben des zweiten users so kurz hinter dem ersten user kommt, das in der queue für die datenbank die abfragen, ob das "ich schreib grad in die datenbank"-bit gerade gesetzt ist "früher" kommt, als das "commit" das der erste user in die datenbank schreibt und somit das "ich schreib grad in die datenbank"-bit vom ersten user gesetzt wird.
im normalen betrieb sollte dies ja eigentlich nie auftreten, aber aufgrund von latenzzeiten im netzwerk kann dieser fall auftreten und ich möchte dies halt abfangen.
hoffe, das ist verständlich :wink:
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Defnull hat Dir doch schon die Lösung dafür gepostet!
Benutzeravatar
gkuhl
User
Beiträge: 600
Registriert: Dienstag 25. November 2008, 18:03
Wohnort: Hong Kong

Defnull hat ihn aber auch nochmal gebeten, das Problem detailierter zu beschreiben. :wink:
Benutzeravatar
Defnull
User
Beiträge: 778
Registriert: Donnerstag 18. Juni 2009, 22:09
Wohnort: Göttingen
Kontaktdaten:

Ich bat ihn aber auch, sein Problem näher zu beschreiben.

Warum arbeiten verschiedene Personen mit der selben Test-Datenbank, obwohl die Daten ja offensichtlich während des Tests verändert werden? Sollte nicht jede Person ihre eigene Testdatenbank haben, damit sie sich nicht in die Quere kommen?
Bottle: Micro Web Framework + Development Blog
The Spirit
User
Beiträge: 276
Registriert: Freitag 8. Juni 2007, 08:50
Wohnort: 84xxx Bereich
Kontaktdaten:

da hab ich mich wohl etwas missverständlich ausgedrückt.
letztendlich wird es eine große datenbank auf die alle zugriff haben werden.
daher das eigentlich problem.
Benutzeravatar
noisefloor
User
Beiträge: 3854
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

ich verstehe das Problem und auch nicht.

Letztendlich ist es doch der Job der DB, parallele Zugriffe auf Daten zu vermeiden - was ja auch alle DBs können. D.h. händisch da parallel was zu machen ist IMHO immer falsch bzw. überflüssig.

Wenn ich das richtig verstehe dann geht es drum, doppelt Einträge zu vermeiden, richtig? Nur sieht man nicht immer, ob ein doppelter Eintrag angelegt würde, weil der Vorgang des Anlegens dauert. Richtig?

Das könnte man so implementieren:

Entweder die DB hat nur eine Tabelle, dann kann eh' nur einer in die Tabelle schreiben ;-)

Wenn man aber mehrere Tabellen haben muss (ist ja auch sinnvoll ;-) ) dann könnte man einen Lock auf die ganze DB setzen (keine Ahnung, ob das mit MySQL geht).

Wie auch immer, beides ist natürlich nicht gerade performant...

Gruß, noisefloor
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

Als Alternative könntest du auch noch eine Schnittstelle zwischen Datenbank und dem/den Testprogrammen einfügen, die so einen Lock mit atomaren Operationen bereitstellt.
Benutzeravatar
noisefloor
User
Beiträge: 3854
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

recht elegant wäre auch, wenn man die Testdaten so strukturieren kann, dass diese über den Primärschlüssel identifizieren kann. Dann kannst du dir auch die Abfrage "Gibt's das schon?" fragen. :-)

Gruß, noisefloor
amiganer68
User
Beiträge: 18
Registriert: Mittwoch 1. Juli 2009, 14:20

Hallo!

Eine Sache ist unnötig: Das selber gemachte Schreib-Lock. Warum? Weil der Datenbank-Server das alleine macht. Der kann das sogar besser als man es selber je nachmachen könnte, da er in der Regel nicht die ganze Datenbank blockieren muß, bis der Schreibvorgang beendet ist.

Wenn Du auch weiterhin alle Einträge direkt in die Zeildatenbank schreiben läßt, dann kommst du um das Abfangen der Doppeleinträge nicht drum herum. Hier sollte es ausreichen, die Exception in Python abzufangen. Ein vorheriges Afragen des vorhanden seins ist auch möglich.

Etwas einfacher wird es hiermit: http://dev.mysql.com/doc/refman/5.1/de/ ... icate.html
Wenn ich das richtig verstanden habe, dann kann mit dem ON DUPLICATE UPDATE" ein Datensatz eingefügt werden, der doppelt ist, also ohne einen Error zu werfen und trozdem kein doppelter Eintrag.

Eine andere Idee: Jeder Kandidat schreibt zuerst in eine Leer-Datenbank, jeder für sich in seine eigene und dann laßt Du die Datenbank diese Daten zusammen kopieren. Das geht dann über einen INSERT .... SELECT...

MfG
Christian
amiganer68
User
Beiträge: 18
Registriert: Mittwoch 1. Juli 2009, 14:20

Hallo zum 2ten

Mir ist da gerade eine neue Idee gekommen:

Definiere für deine Datenbank einen Primarykey, der als autoincrement von der Datenbank selbstständig gesetzt wird. Dann trage einfach deine Daten per INSERT ein, danach einen "DELETE daten WHERE datenerster=datenzweiter AND primarykeyerster ungleich primarykeyzweiter". Das kannst du sogar nach jedem INSERT direkt machen, dann mußte du keine exceptions abfangen, denn der INSERT Befehlt klappt immer, dein UNIQUE mußte dafür aber raus nehmen, dann für kurze Zeit kann es doppelte geben.

MfG
Christian
Antworten