Rollbacks und solche Dinge...
rolfrost
- datenbank
Hallo,
in meiner Praxis (ooch wie soll ich das sagen... Arzt bin ich nicht) greife ich für meine Datenhaltung gerne auf Berkeley DB's zurück.
Auf
http://i-netlab.de/cgi-bin/index.cgi?display=40.17
(ein alter aber nunmehr wieder aufpolierter Artikel)
beschreibe ich ein Problem was besteht, wenn 2 Benutzer gleichzeitig einen bestimmten Datenbestand in ein EditFenster laden und nun nacheinander versuchen ein Update zu machen. Was könnte passieren? Möglich ists, dass von A eingegenen neue Daten von B überschrieben werden - weil B zum Zeitpunkt seines Update-Versuches den mittlerweile neuen Datenbestand (geschrieben von A) nicht kennt.
Für meine geliebten Berkeley DBs hab ich somit eine Lösung gefunden...
Frage: Wenn ich MySQL o.a. RDBMS verwende und vermittels CGI Updates auf bestimmte Tabellen machen will - muss ich mich da um solche Sachen auch selber kümmern? Oder macht das die Engine?
Viele Grüße, Rolf
Servus,
mir ist nur bekannt, dass Oracle das je nach Einstellung übernimmt oder es Dir überlässt.
Für Java EJB Applikationen hat sich das gewisserweise erledgt, weil die Bea die Persitenz selber handelt und damit solche aufgaben übernimmt.
Bei CGI Scripten und MySQL jedoch glaube ich zu wissen, dass du dich selber darum kümmern muss. !!Kann aber inzwischen schon wieder überholt sein meine Ausage. Hab schon seit 3 Jahren keine MySQL mehr angefasst.
Gruss Matze
Hi Rolf,
lies Dir vielleicht das mal durch:
http://www.mysql.com/doc/en/LOCK_TABLES.html
http://www.mysql.com/doc/en/COMMIT.html
Gruß
Reiner
hi Reiner,
lies Dir vielleicht das mal durch:
http://www.mysql.com/doc/en/LOCK_TABLES.html
http://www.mysql.com/doc/en/COMMIT.html
commit - ja denkst du ich bin vorhin auf diesen fuc* Begriff gekommen? Das isses! Vielen Dank, morgen klick ich mir deine Links....
Viele Grüße, Rolf
Moin!
lies Dir vielleicht das mal durch:
http://www.mysql.com/doc/en/LOCK_TABLES.html
http://www.mysql.com/doc/en/COMMIT.htmlcommit - ja denkst du ich bin vorhin auf diesen fuc* Begriff gekommen? Das isses! Vielen Dank, morgen klick ich mir deine Links....
Das Problem ist, dass diese Mechanismen das Problem nicht lösen.
Transaktionen sind dazu da, mehrere einzelne Operationen zu einer atomaren Operation zusammenzufassen - also beispielsweise, wenn man mehrere Tabellen mit mehreren UPDATES/INSERTS verändern muß, um beispielsweise eine Kontobuchung auszuführen (das Geld darf ja nicht mittendrin verloren gehen).
Und LOCKs sperren zwar die Tabelle für eine gewisse Zeit, damit ein einzelner Prozess daran arbeiten kann, aber auch nicht für immer.
Das Problem des gleichzeitigen Arbeitens an einer DB ist aber, dass zwei Arbeiter einen Datenbestand aus der DB auslesen und ausgehend von diesem Stand unterschiedliche Änderungen einspielen wollen - zeitlich versetzt.
Die zwei vorgestellten Mechanismen des Artikels sind in meinen Augen wirklich die einzigen Möglichkeiten, das zu regeln.
Also entweder einen Datensatz per Eintrag in diesen Datensatz für alle anderen Benutzer auch zum Lesen zu sperren (und damit erst recht zum Schreiben), oder mit Timestamp zu arbeiten, um den damals ausgelieferten Stand mit dem derzeit vorliegenden Stand zu vergleichen und den Konflikt erkennen zu können.
Das Locking hat den beschriebenen Nachteil: Wer löscht den Lock auf einen Datensatz?
Der Timestamp hat immerhin noch den Nachteil, dass der zweite Benutzer, der den Konflikt angezeigt kriegt, im Prinzip nur den neuen, geänderten Stand sowie seine Änderungen kennt, aber nicht mehr den alten Stand. Welche Daten läßt er dann überschreiben? Man müßte also irgendwie die Unterschiede feststellen.
Wenn User A die Postleitzahl geändert hat, und User B den Namen, wird das für User B irgendwie offensichtlich sein: Ihm wird der derzeitige DB-Eintrag gezeigt, bei dem sich PLZ und Name jeweils unterscheiden, er weiß noch, dass er den Namen geändert hat, also wird die PLZ von User A geändert worden sein - dann muß er das Update nur noch passend zusammensetzen.
Was aber, wenn beide die PLZ geändert haben? Bei identischer Änderung kein Problem - war zwar doppelte Arbeit, aber der Datensatz ist ja schon von User A geändert, User B ändert nichts mehr. Der Konflikt ist also keiner, weil der zu schreibende Datensatz dem bereits geschriebenen entspricht.
Wenn aber die Original-PLZ von A und B unterschiedlich geändert wurde, was ist dann korrekt? Das Original ist in der DB verloren, seit A gespeichert hat, und B sieht, dass seine PLZ mit der von A konkurriert. Der Konflikt ist unlösbar, ohne dass sich A und B verständigen, was denn nun passieren soll.
Bei so simplen Dingen wie einer Postleitzahl dürfte das Problem der Abstimmung noch gering sein, aber wenn beispielsweise Textpassagen geändert wurden, kann man das DB-Feld nicht mehr in seiner Gesamtheit betrachten, sondern muß Textanalyse betreiben, um herauszufinden, ob die Änderungen zu einem Konflikt führen. Das Tool "diff" könnte hierbei hilfreich sein, um zeilenweise Texte miteinander zu vergleichen und ggf. Änderungen, die an komplett unterschiedlichen Orten stattfinden (A ändert ganz oben, B ganz unten), automatisch zu einer neuen Version zusammenzuführen.
Eventuell ist es auch eine gute Idee, sämtliche ändernden Zugriffe auf die DB in ein Logfile oder eine Log-Tabelle zu schreiben. Damit könnte man im Notfall den vorherigen Zustand wiederherstellen. Beispielsweise könnte man alle UPDATEs und INSERTs dort direkt ablegen und ggf. einfach noch mal bis zu dem gewünschten Zeitpunkt auf die DB loslassen. Sowas dürfte aber ziemlich aufwendig sein.
- Sven Rautenberg
moin Sven,
vielen Dank für Dein Feedback!
Das Problem ist, dass diese Mechanismen das Problem nicht lösen.
Transaktionen sind dazu da, mehrere einzelne Operationen zu einer atomaren Operation zusammenzufassen - also beispielsweise, wenn man mehrere Tabellen mit mehreren UPDATES/INSERTS verändern muß, um beispielsweise eine Kontobuchung auszuführen (das Geld darf ja nicht mittendrin verloren gehen).
Gottseidank gehts in meinen Anwendungen nicht direkt um Geld ;-)
(IP - Adressverwaltung, Auftragsabwickelungen: Bearbeiten von Anträgen...)
Und LOCKs sperren zwar die Tabelle für eine gewisse Zeit, damit ein einzelner Prozess daran arbeiten kann, aber auch nicht für immer.
Das Problem des gleichzeitigen Arbeitens an einer DB ist aber, dass zwei Arbeiter einen Datenbestand aus der DB auslesen und ausgehend von diesem Stand unterschiedliche Änderungen einspielen wollen - zeitlich versetzt.
Die zwei vorgestellten Mechanismen des Artikels sind in meinen Augen wirklich die einzigen Möglichkeiten, das zu regeln.
Also entweder einen Datensatz per Eintrag in diesen Datensatz für alle anderen Benutzer auch zum Lesen zu sperren (und damit erst recht zum Schreiben), oder mit Timestamp zu arbeiten, um den damals ausgelieferten Stand mit dem derzeit vorliegenden Stand zu vergleichen und den Konflikt erkennen zu können.
Das Locking hat den beschriebenen Nachteil: Wer löscht den Lock auf einen Datensatz?
Jow - das ist wirklich ein Problem, evntl. im Intranet lösbar wo sich die user telefonisch oder durch Zuruf verständigen können...
Der Timestamp hat immerhin noch den Nachteil, dass der zweite Benutzer, der den Konflikt angezeigt kriegt, im Prinzip nur den neuen, geänderten Stand sowie seine Änderungen kennt, aber nicht mehr den alten Stand. Welche Daten läßt er dann überschreiben? Man müßte also irgendwie die Unterschiede feststellen.
Programmiertechnisch ist das möglich, sowas einzubauen:
-userA und userB laden einen bestimmten Datenbestand
Ort=alter Ort, PLZ=alte PLZ
-userA macht Update mit:
Ort=neuer Ort, PLZ=neue PLZ
-userB will Update machen, er hat:
Ort=alter Ort, PLZ=neue PLZ
userB bekommt einen Hinweis dass die Daten geändert wurden und er bekommt angezeigt:
-die Änderungen die userA gemacht hat
+die Änderungen die erselbst einpflegen will
Somit kann userB entscheiden.... in meinen Anwednungen hab ich das wenigstens so gemacht, dass userB im Falle dass userA was geändert hat - sofort wieder in den *EditModus* kommt und die nunmehr aktuellen Daten sieht. Das ist recht einfach und hat sich bewährt, denn bereits hier kann userB sehen ob er überhaupt noch was machen muss.
Eventuell ist es auch eine gute Idee, sämtliche ändernden Zugriffe auf die DB in ein Logfile oder eine Log-Tabelle zu schreiben. Damit könnte man im Notfall den vorherigen Zustand wiederherstellen. Beispielsweise könnte man alle UPDATEs und INSERTs dort direkt ablegen und ggf. einfach noch mal bis zu dem gewünschten Zeitpunkt auf die DB loslassen. Sowas dürfte aber ziemlich aufwendig sein.
Die Idee ist wirklich gut, das ist die Grundlage für Rollbacks und in jedem RDBMS implementiert. Alternative für eigene Entwicklungen: RCS (Revision Control System).
Viele Grüße, Rolf
Hallo,
Das Locking hat den beschriebenen Nachteil: Wer löscht den Lock auf einen Datensatz?
Jow - das ist wirklich ein Problem, evntl. im Intranet lösbar wo sich die user telefonisch oder durch Zuruf verständigen können...
Oder aber durch einen cronjob (oder vergleichbares), der 'alte' Locks einfach wieder aufhebt.
Eventuell ist es auch eine gute Idee, sämtliche ändernden Zugriffe auf die DB in ein Logfile oder eine Log-Tabelle zu schreiben. Damit könnte man im Notfall den vorherigen Zustand wiederherstellen. Beispielsweise könnte man alle UPDATEs und INSERTs dort direkt ablegen und ggf. einfach noch mal bis zu dem gewünschten Zeitpunkt auf die DB loslassen. Sowas dürfte aber ziemlich aufwendig sein.
Die Idee ist wirklich gut, das ist die Grundlage für Rollbacks und in jedem RDBMS implementiert. Alternative für eigene Entwicklungen: RCS (Revision Control System).
Das wegschreiben eines Datensatzes bei jedem UPDATE ist dann noch relativ einfach, wenn man eine Datenbank verwendet, bei denen Trigger bzw Storder-Procedures möglich sind. Ein BEFORE UPDATE-Trigger schreibt beispielsweise den ganzen Datensatz in eine Archiv-Tabelle (vielleicht mit Timestamp und einer Benutzerkennung) aus der dann ältere Stände restauriert werden können.
Grüße
Klaus