Multiuserbetrieb und Zeilen zeitweise Sperren, sowas wie ein "Edit-Flag". Gute Idee?
-
Hallo,
meine Software wird auf mehreren Arbeitsstationen betrieben. Zentral gibt es eine Datenbank.
Nun bereitet es mir etwas Kopfzerbrechen, wie ich den Mehrbenutzerzugriff ohne Inkonsistenzen in den Griff bekommen soll.
Zum Beispiel gibt es eine Kundenliste in der Datenbank. Wird ein bestimmter Kunde nun bearbeitet (was länger dauert) muss ich sicherstellen, dass der Eintrag währenddessen nicht von einer anderen Arbeitsstation gelöscht wird.
Es gibt etliche Tabellen mit z.B. Messergebnissen die alle Fremdschlüsselbeziehungen zum Kundeneintrag haben. Wird der gelöscht, geht alles schief.
Naja ein Edit-Flag wäre mir ab liebsten. Das schützt vor Löschungen an anderen Stationen. Nur was tun, wenn DIE Station abstürzt, die das Edit-Flag gesetzt hat? Dann wird die der Datensatz nie wieder freigegeben...
Eine Dienst auf dem Rechner mit der Datenbank kommt nicht in Frage: Die Clienten müssen sich irgendwie einig werden, und zwar OHNE Kommunikation untereinander. Die kennen nur den Datenbankserver.
Scheint mir kaum lösbar zu sein, oder?
-
Google doch mal nach Datenbank-Transaktionen, pessimistische und optimistische Sperrverfahren.
-
Grob skizziert:
Daten holen, merken, anzeigen.
Edit geht auf extrige Kopie der Daten. Das kann dauern so lange will (ist ja nichtmal ne Transaktion offen während editiert wird).
Wenn User save klickt, dann Transaktion aufmachen, aktuelle Daten nochmal aus der DB holen, mit den gemerkten "Originalen" vergleichen.
Wenn ungleich dann ROLLBACK + User fragen was tun soll.
Wenn gleich dann mit der editierten Kopie überschreiben und COMMIT.p.S.: das Locking der DB würde ich ganz sicher *nicht* für sowas verwenden wollen. Nicht weil ich dem nicht vertraue, sondern weil du dadurch etwas blockierst, was du nicht blockieren solltest. Nämlich dass man mit dem System arbeiten kann.
Im Prinzip ist das das selbe, was Systeme wie Subversion machen. Also Edit/Merge/Commit.
-
@hustbaer:
Ich habe etliche Tabellen die mit Fremdschlüsseln auf den Kundensatz zeigen + externe Daten (Bilder).
Nur den Kundeneintrag zu kopieren reicht also nicht, es müsste alles irgendwo temporär gespeichert werden solange die "Sitzung" mit dem Kunden läuft. Und später alles vergleichen, das ist ja die Hölle. Meinst Du das echt so?"Nicht weil ich dem nicht vertraue, sondern weil du dadurch etwas blockierst, was du nicht blockieren solltest"
Eigentlich schon, es wird der eine Kundensatz gesperrt. Alle anderen können an parallelen Stationen bearbeitet werden.
-
Ich mache das so, das ich im Datensatz einen Sperrvermerk habe (User sind immer über Benutzername identifizierbar).
Wenn Jemand auf "Edit" in der Anwendung klickt mache ich erst ein Update auf den Sperrvermerkt:
"UPDATE table SET sperre='username' WHERE sperre='' AND id=0815;"
Wenn mir die DB zurückliefert, das ein Datensatz geändert wurde, hab ich mir den Datensatz erfolgreich reserviert, sonst war jemand anderes schneller.
Beim speichern oder abbrechen lösche ich die Sperre wieder, wenn mein Benutzername drin steht.Problem:
Semmelt die Anwendung ab, bleiben gesperrte leichen über. Da gibts ne möglichkeit diese nachträglich freizugeben.mfg
xXx
-
UndEsIstSommer... schrieb:
@hustbaer:
Ich habe etliche Tabellen die mit Fremdschlüsseln auf den Kundensatz zeigen + externe Daten (Bilder).
Nur den Kundeneintrag zu kopieren reicht also nicht, es müsste alles irgendwo temporär gespeichert werden solange die "Sitzung" mit dem Kunden läuft. Und später alles vergleichen, das ist ja die Hölle. Meinst Du das echt so?"Nicht weil ich dem nicht vertraue, sondern weil du dadurch etwas blockierst, was du nicht blockieren solltest"
Eigentlich schon, es wird der eine Kundensatz gesperrt. Alle anderen können an parallelen Stationen bearbeitet werden.Ja ich meinte das echt so. Da wusste ich noch nicht dass es sich um so grosse Daten handelt.
Es gibt aber auch so schöne "change indicator"/"change counter" Datentypen, die dir der SQL Server automatisch ändert/hochzählt, wenn irgendwas in der Zeile modifiziert wird.
Kann man auch verwenden um festzustellen ob es Edits dazwischen gab.
-
Ich verwende für sowas optimistisches Locking und eine Hilfstabelle. In die kommt Username, Session ID, Tabelle und Primärkennung des Datensatzes. Wenn nun jemand anders versucht den Satz zu bearbeiten wird zunächst die Hilfstabelle abgefragt (Dabei die Session ID gecheckt um tote Sitzungen auszuschliessen) und ggf. eine Meldung ausgegeben "Wird gerade bearbeitet durch User Horst".
Diese Konstruktion ist ausschliesslich für das Frontend gedacht. Wenn Systemprozesse einen Konsistenzfehler verursachen, wird dies durch die Datenbank- und Session-Einstellungen gehandled, die vorher entsprechend konfiguriert wurden (Nowait ein, Iso Level auf Read Commited usw).