Satz sperren für Änderung
Kalle_B
- datenbank
0 Frank (no reg)0 Kalle_B2 Sven Rautenberg0 Kalle_B
0 Hamstar
0 lulu0 Hamstar
Hallöle,
meine Datenbank ist MySQL 4.1.9-log
Wenn ein Benutzer eine Adresse zum Ändern aufruft, vergeht eine unbestimmte Zeit, bis er das Formular zurückschickt (Mittagspause, Konferenz, ...).
Wenn ich anderen Benutzern auch erlaube, dieselbe Adresse zu ändern, gibt es natürlich ein heilloses Durcheinander. Der letzte überschreibt die Änderung der anderen.
Nun könnte ich ja einen Sperrvermerk im Datensatz machen (Für User "Kalle" bis 5:30 reserviert).
Das war ein Trick aus uralten DOS- Zeiten. Heute macht man das wahrscheinlich anders? Wie ist das Konzept?
Gruß, Kalle
Hi,
naja, du fügst ein Feld der Tabelle hinzu, speicherst darin deine Sperrungsdaten. Die Sperrungsdaten werden erzeugt, wenn die "Adresse zum Ändern" aufgerufen wird. Ist das Feld zu dem ZEitpunkt NULL, kann eine Sperrung erfolgen, ansonsten behandelst du den anderen Zustand als Fehlerfall und erweitertst deine Programmlogik entsprechend (Redirect) o.ä.. Wenn dann erfolgreich gespeichert wurde, setzt du das Sperrfeld wieder auf NULL.
Ciao, Frank
Moin!
naja, du fügst ein Feld der Tabelle hinzu, speicherst darin deine Sperrungsdaten. Die Sperrungsdaten werden erzeugt, wenn die "Adresse zum Ändern" aufgerufen wird. Ist das Feld zu dem ZEitpunkt NULL, kann eine Sperrung erfolgen, ansonsten behandelst du den anderen Zustand als Fehlerfall und erweitertst deine Programmlogik entsprechend (Redirect) o.ä.. Wenn dann erfolgreich gespeichert wurde, setzt du das Sperrfeld wieder auf NULL.
Alternativ wird beim Abrufen der Daten aus der Tabelle dieser Originalzustand mit gespeichert und beim erneuten Beschreiben zunächst die Unverändertheit der bisherigen Daten festgestellt.
Sollte sich die DB in der Zwischenzeit geändert haben, kann man zunächst in einem automatischen Schritt feststellen, ob sich die Änderung auf alle Datenfelder auswirkt, oder nur auf einzelne (z.B. zwischenzeitlich ist nur die Telefonnummer geändert worden), die vom aktuellen Bearbeitungsschritt nicht geändert wurden. In so einem Fall lassen sich beide Änderungen störungsfrei zusammenfassen.
Oder man fügt einen manuellen Bearbeitungsschritt ein, der den Originalzustand, die Änderungen des aktuellen Benutzers und die zwischenzeitlich eingetretene Änderung in der DB auflistet und eine manuelle Zusammenfügung der Daten verlangt. Sofern der automatisierte Schritt stattfindet (was nicht zwingend die beste Lösung sein muß), wären an diesem Punkt nur Felder betroffen, die von beiden Benutzern parallel und unterschiedlich geändert wurden.
Allerdings muß man beachten, dass der aktuelle Benutzer nicht unbedingt den Hintergrund der zwischenzeitlichen Bearbeitung kennt und möglicherweise einfach seine Änderung in die Datenbank packt, ohne zu recherchieren, welche Information (seine oder die des zwischenzeitlichen Bearbeiters) denn korrekt ist.
- Sven Rautenberg
Hallöle,
mmmh, recht umfangreich. Eigentlich hatte ich auf so was einfaches gehofft wie "read_for_update", und die DB kümmert sich.
Habe ich doch schon irgendwo gehört. Bei Oracle vielleicht?
Wenn mehrere Tabellen von einer Änderung betroffen sind, kann ich ja ein eigenes Projekt aufmachen ...
Gruß, Kalle
Moin!
mmmh, recht umfangreich. Eigentlich hatte ich auf so was einfaches gehofft wie "read_for_update", und die DB kümmert sich.
Habe ich doch schon irgendwo gehört. Bei Oracle vielleicht?
Wenn mehrere Tabellen von einer Änderung betroffen sind, kann ich ja ein eigenes Projekt aufmachen ...
Dein Problem mit dem parallelen Bearbeiten von Datenbankdaten ist identisch zum parallelen Bearbeiten von Quelltexten.
Für Quelltexte gibt es diverse Versionskontrollsysteme (CVS, Subversion,...), und keines ist "einfach". Alle schlagen sich mit dem Problem herum, dass insbesondere das unterschiedliche Verändern der gleichen Programmzeile zu Konflikten führt, die irgendwie gelöst werden müssen.
Die Methode des Sperrens der Daten gegen Veränderung durch Dritte hilft im Konfliktfall genausowenig, wie die Methode des Zusammenführens und manuellen Bearbeitens.
Das Sperren hat das Problem festzustellen, wann die Sperre wieder entfernt werden kann. Wenn der Bearbeiter zwei Stunden Mittagspause macht (oder auch nur fünf Minuten an dem Datensatz sitzt), und während dieser Zeit muß ein anderer Bearbeiter einfach nur die Telefonnummer ändern, weil der Kunde gerade angerufen hat - und kann das nicht, weil der Datensatz gesperrt ist, dann wird ihn die Zurückweisung seiner Daten extrem nerven und von der Arbeit abhalten.
Das Zusammenführen der Änderungen (Merging) in der Form der Versionskontrollsysteme reduziert diese Konflikte auf die Fälle, in denen tatsächlich das gleiche Datenfeld zweimal in unterschiedlicher Form geändert wurde. Der als zweiter speichernde Bearbeiter hat dann zwar die u.U. schwierige Aufgabe, zu entscheiden, welche Änderung korrekt ist und überlebt, bzw. muß die Änderungen irgendwie zusammenführen (Hintereinanderhängen von zwei Kommentaren wäre ja denkbar), aber er wird solch eine Aktion deutlich seltener durchführen, als durch Sperren behindert werden.
Alternativ kannst du natürlich auch einfach nur die Sessiondauer begrenzen und nach Ablauf einer Zeitperiode das Formular als ungültig zurückweisen - blöd ist dann nur, wenn die Bearbeitung der Daten, Recherche etc., länger gedauert hat, und die Änderungen dadurch verloren gehen würden.
AJAX kann in diesem Zusammenhang übrigend helfen, das doch sehr starre Konzept des "submit complete form" aufzubrechen. Allerdings nicht ohne Preis: Eventbasiert den Client serverseitig von zwischenzeitlichen Änderungen in der Datenbank zu informieren funktioniert in HTTP natürlich auch mit AJAX noch nicht, es sind daher andauernde Requests zum Server notwendig, die entsprechend Performance kosten und natürlich auch hinreichend abgesichert sein müssen.
- Sven Rautenberg
Moin, Sven,
danke für deine sehr ausführliche Stellungnahme.
Ich denke, ich sperre den Satz für eine gewisse Zeit gegen Änderungen weiterer User.
Das Sperren hat das Problem festzustellen, wann die Sperre wieder entfernt werden kann.
Entweder nach Uhrzeit oder berechtigter Änderung. Was eher eintritt.
Wenn der Bearbeiter zwei Stunden Mittagspause macht (oder auch nur fünf Minuten an dem Datensatz sitzt), und während dieser Zeit muß ein anderer Bearbeiter einfach nur die Telefonnummer ändern, weil der Kunde gerade angerufen hat - und kann das nicht, weil der Datensatz gesperrt ist, dann wird ihn die Zurückweisung seiner Daten extrem nerven und von der Arbeit abhalten.
Na, dann muss er sich ausnahmsweise eine Notiz machen. Es nervt auch, wenn ich Leute anrufen will und da ist besetzt.
Alternativ kannst du natürlich auch einfach nur die Sessiondauer begrenzen und nach Ablauf einer Zeitperiode das Formular als ungültig zurückweisen - blöd ist dann nur, wenn die Bearbeitung der Daten, Recherche etc., länger gedauert hat, und die Änderungen dadurch verloren gehen würden.
Deshalb wollte ich ja die Ende- Uhrzeit der Sperrung anzeigen. Habe dann aber wahrscheinlich das Zeitzonenproblem.
Die Daten werden nach Ablauf der Sperrzeit zwar abgewiesen, aber im Formular angezeigt. Muss dann eben in ein frisches Formular übertragen werden. Das wird der "Schnecke", die soo lange brauchte, dann auch wohl nichts ausmachen ;-)
AJAX ...
mal schauen, so langsam arbeite ich mich da ein. Kommt aber eher infrage, um die Liste upzudaten, nachdem ein Eintrag bearbeitet wurde.
Gruß, Kalle
mmmh, recht umfangreich. Eigentlich hatte ich auf so was einfaches gehofft wie "read_for_update", und die DB kümmert sich.
Habe ich doch schon irgendwo gehört. Bei Oracle vielleicht?
Um was soll sich die "DB" kümmern? Um die Konfliktverwaltung? Um das "Sperren" von Datensätzen? Oder einfach um alles?
;-)
Wenn mehrere Tabellen von einer Änderung betroffen sind, kann ich ja ein eigenes Projekt aufmachen ...
In der Tat, eine reizvolle Aufgabe. Schon mal solche Anforderungen gehabt wie vollständige Historiesierung mit Regelverwaltung für Konflikte?
Huhu Kalle,
eine einfache Lösung könnte so ausschauen:
Beim Auslesen der Daten erzeugst Du eine Prüfsumme.
Diese wird beim Update mitgeschickt.
Anhand der Anzahl der betroffenen Datensätze (affected rows, 1 oder 0) kannst Du dann
sagen "ok" oder "Der Datensatz wurde zwischenzeitlich verändert".
SELECT
a,b,c,
MD5(concat_ws('#',id,a,b,c)) as hasherl
FROM
TableName
WHERE
id=123
UPDATE
TableName
set
[...]
WHERE
id=123
AND
MD5(concat_ws('#',id,a,b,c)) = '$hasherl'
Viele Grüße
lulu
eine einfache Lösung könnte so ausschauen:
Beim Auslesen der Daten erzeugst Du eine Prüfsumme.
Diese wird beim Update mitgeschickt.
Anhand der Anzahl der betroffenen Datensätze (affected rows, 1 oder 0) kannst Du dann
sagen "ok" oder "Der Datensatz wurde zwischenzeitlich verändert".
Na ja, wird der Nutzer, der den Datensatz gerade bearbeitet hat, denn auch happy sein mit der Auskunft, dass die Änderungen "leider nicht übernommen werden konnten."?
Besser da schon das Auschecken von Datensätzen, von einer Konfliktverwaltung würde ich auch die Finger lassen wollen.
Statt Prüfsumme also wohl besser Zeitstempel.