Konkurierende Datenbankzugriffe verhindern

N

nibel

Doppel-As
Hallo Gemeinde,

ich bin gerade dabei hier eine Software in PHP für telefonische Kundenbefragungen zu erweitern, der verwendete DB-Server ist Mysql:

Konkret geht es um die Zugriffe auf die einzelnen Kundendatensätze, der vorherige Programmierer hat dabei jeweils einen Timestamp für den letzten Zugriff weggeschrieben und darauf geprüft, damit dieser nicht gleichzeitig geöffnet wird und nach dem letzen Zugriff ne gewisse Zeit vergeht, bevor er noch Mal angefasst wird.

Nun wurden aber weitere Mitarbeiter auf die Telefonie angesetzt, nun kommt es immer häufiger vor, Mitarbeiter B auf den Datensatz zugreift, bevor Mitarbeiter A, welcher ebenfalls diesen Datensatz bearbeiten will seinen Timestamp weggeschrieben hat..

Wie kann ich dieses Verhalten am elegantesten und bequemsten unterbinden?

Wenn es keine Webapplikation wäre, würde ich einen Dienst laufen lassen, welcher den einzelnen Mitarbeitern die ID's zuweist....

Bietet die Datenbank geeignete Funktionalitäten, um dies zu verhindern?

Kann ich irgendwie ne Queue bauen, oder sollte ich mit locks arbeiten?

Danke und VG
 
Entschuldige bitte, ich hab nicht wirklich Ahnung von DBs, aber realisiert das nicht der DB Sheduler?
 
Der ist wohl eher eine "Cron-Lösung" für Stored Procedures.
 
Du könntest einen Spread Message Bus - http://spread.org/ - hinter die Webapp klemmen. Auf diesen könntest du eine Nachricht setzen, dass Datensatz mit der ID NN gerade in Benutzung ist und die Webapp schaut zuerst auf dem Message Bus nach ob dort die ID des Datensatzes zu finden ist. Nur wenn sie dort nicht ist, öffnet sie den Datensatz.

Mit Locks wirst du vermutlich nicht weit kommen. Diese beziehen sich auf ganze Tabellen. Allgemein sollten sich konkurrierende Zugriffe aber durch Transaktionen verhindern lassen. Wie oft ein Datensatz offen ist, sollte ja keine grosse Rolle spielen. Man will ja lediglich beim Speichern/Schreiben die Race Conditions vermeiden.
 
Da hast du mich auf ne Idee gebracht! Spread klingt echt toll ich werde es mir mal anschauen, allerdings überlege ich, ob ich das nicht auch mit Memcached hin bekomme.
 
Auch mit memcached sollte das machbar sein. Allerdings solltest du irgendwie (z.B. über einen Cronjob) sicherstellen, dass beim Runterfahren des Systems die Daten aus dem Memcache mit der DB synchronisiert werden. Bei einem Stromausfall hast du allerdings schlechte Karten, wenn du keine USV einsetzt.
 
Bin jetzt auch kein Datenbank-Experte, aber kannst du nicht in deiner Tabelle eine Spalte "Lock" (bool) hinzufügen und diese zum Sperren das Datensatzes verwenden? Ein Benutzer, der auf einen Datensatz zugreift setzt Lock=true und alle anderen können dann eben nur lesen, bis der Datensatz wieder freigegeben wurde.

magixD

Edit: Ist natürlich blöd wenn zwei Benutzer gleichzeitig darauf zugreifen, dann locken beide die Tabelle und beide Denken sie dürften schreiben. Etwas abgewandelte Idee:
Du schreibst in die Lock-Spalte die BenutzerID (oder den Computer-Namen, oder sonst irgend einen eindeutige Zeichenkette). Ein Benutzer, der den Datensatz öffnet schaut nun ob Lock leer ist, wenn ja schreibt er seine ID und liest dann das Lock-Feld noch einmal aus: steht seine ID drinnen hat er gewonnen, steht eine andere drinnen gab es einen plesiosynchronen Zugriff und der andere hat gewonnen.
 
Man könnte es auch so machen: Wenn die Telefonisten den Eintrag öffnen wird erstmal nichts geprüft o.ä., da die Daten ja manchmal nur betrachtet werden. Jeder Eintrag hat aber eine Zeit der letzten Bearbeitung gespeichet, die auf der Webseite z.B. in einem hidden input mit gespeichert ist. Wenn jetzt das Formular gesendet wird, also gespeichert wird, wird verglichen, ob der gesendete Timestamp mit dem im Datensatz übereinstimmt. Ist er gleich, wird einfach gespeichert und ein neuer Timestamp gesetzt. Ist er anders, hat also zwischenzeitlich jmd anderes gespeichert, wird der neue Datensatz mit dem Formular angezeigt und der Benutzer kann dann entscheiden, ob er wirklich Überspeichern will oder Änderungen einpflegen.
 
Zurück
Oben