Hi Andreas,
Ja, genau so mache ich es bereits. Das Problem liegt wo anders. Wenn jemand einen Datensatz zum bearbeiten aufruft, ab diesem Moment darf das niemand anders mehr machen können,
doch, darf er. Nur muß die bereits begonnene Transaktion zum Zeitpunkt ihres "commit" merken, daß jemand anderes ihr zuvor gekommen ist (beispielsweise über WHERE-Klauseln ihrer UPDATE-Statements). Diese Transaktion wird dann scheitern, und Dein Skript muß mit dieser Situation fertig werden.
Anwender 1 öffnet die Daten zum bearbeiten, die Daten werden mit einem Flag versehen, so dass niemand anderes mehr drankommt.
Das wäre der "pessimistische" Ansatz. Der "optimistische" scheint mir performanter zu sein - je nach Randbedingungen (siehe unten).
Nur - was ist wenn Anwender 1 die Daten bearbeiten will, daber aber ein Problem auftaucht
Dann muß Dein Skript dieses Problem lösen. Vielleicht schickt es den Anwender zurück zum Schritt 1 des Dialogs; vielleicht kann es die transaktionsrelevanten Daten selbst anpassen; vielleicht gibt es eine Meldung aus, daß diese Daten bereits eingegeben wurden. Was davon zutrifft, hängt von Deiner Anwendungslogik ab.
Und Du mußt in diesem Moment immer noch darauf achten, daß Dir inzwischen die Grundlagen für diese Transaktion entzogen worden sein können, weil jemand anderes weniger als 10 Minuten brauchte, um eine Änderung einzugeben.
Ja, aber das will ich auch nicht.
Für die optimale Lösung Deines Problems ist irrelevant, was Du "willst". ;-)
Wenn Anwender 1 Daten eingibt, soll Anwender 2 eine Fehlermeldung erhalten und nicht ebenfalls Daten eingeben können, denn sonst würden beide parallel Daten eingeben, und einer davon wird das auf jeden Fall um sonst gemacht haben, das ist sehr ärgerlich. Fände ich zumindest.
Wer sagt Dir, daß beide dieselben Daten eingeben? Und wie hoch ist die Wahrscheinlichkeit, daß dieser Fall auftritt? So etwas läßt sich arbeitsmethodisch minimieren, beispielsweise durch Absprachen und Zuständigkeiten - oder durch eine automatische Aufteilung der Eingabedaten.
Entscheidend ist ja nicht, daß es nie Doppeleingaben gibt, sondern daß diese in der Summe nicht teuer werden. Datenverlust fände ich im Vergleich dazu schlimmer.
Wenn allerdings nur genau diese Synchronisation Dein Ziel ist, dann wäre ein triviales Flag in der Tat die einfache Lösung.
Wie bei jeder Synchronisation brauchst Du eine atomare Operation "test and set", um ein Semaphor zuverlässig zu setzen - über eine entsprechende WHERE-Klausel im UPDATE sollte das möglich sein: Wenn mehrere Prozesse versuchen, "UPDATE t_semaphor SET flag=1 WHERE flag=0" (oder wie das in dem entsprechenden SQL-Dialekt gerade heißen mag ...) auszuführen, dann wird anschließend sicherlich das Flag auf 1 stehen, aber die Prozesse sollten unterschiedliche Returncodes über die Ausführung ihrer Statements erhalten.
Löse Dich von der Idee, Deine SQL-Statements auf mehrere Skripte zu verteilen - genau hier liegt Dein Problem.
Das habe ich nie gemacht, ich habe eine Session in die alles reingeschreiben wird, am Ende eien Statusseite wo alle Eingaben kontrolliert werden, und dann einen "Speichern"-Button.
Auch das Setzen Deines Flags ist ein Teil des transaktionsrelevanten Codes: In diesem Moment öffnest Du - semantisch betrachtet - die Transaktion. Und genau das ist Dein Problem: Ab diesem Moment kann viel Zeit vergehen, bis die Transaktion geschlossen wird.
Wenn es Dir wirklich nur darum geht, Doppeleingaben zu verhindern, dann ist ein zuverlässiges Record-Locking wahrscheinlich die beste Lösung - dann jedoch sind alle Deine Fragen, was in bestimmten Problemfällen passiert, separat zu behandeln ... Du kannst innerhalb des Semaphors beispielsweise eine Session-ID speichern, welche bei nachfolgenden Zugriffen auf das gesperrte Objekt ebenfalls abgefragt wird, so daß ein Prozeß erkennen kann, daß ihm sein Semaphor von der Ablaufsteuerung gewaltsam entzogen wurde (timeout etc.).
Viele Grüße
Michael
T'Pol: I apologize if I acted inappropriately.
V'Lar: Not at all. In fact, your bluntness made me reconsider some of my positions. Much as it has now.
(sh:| fo:} ch:] rl:( br:^ n4:( ie:% mo:) va:| de:/ zu:| fl:( ss:) ls:~ js:|)
=> http://www.peter.in-berlin.de/projekte/selfcode/?code=sh%3A|+fo%3A}+ch%3A]+rl%3A(+br%3A^+n4%3A(+ie%3A%25+mo%3A)+va%3A|+de%3A%2F+zu%3A|+fl%3A(+ss%3A)+ls%3A~+js%3A|
Auch diese Signatur wird an korrekt konfigurierte Browser gzip-komprimiert übertragen.