master-f
Goto Top

mysql datensatz nicht überschreiben

kundenverwaltungsprogramm

Hallo alle zusammen,
ich möchte eine kunden datenbank programmieren. Mit welcher art ich darauf zugreife ist eigentlich egal ob es C#, Java oder php ist, eigentlich mit allen.
Wenn man einen kunden aufruft und dessen daten sieht und vielleicht diese ändern möchte erstelle ich ein objekt mit den daten die ich brauche, aus der datenbank, z.B. ID , kunden name und kunden vorname.
Aber es könnte sein das ein anderer benutzer zur gleichen zeit dieses objekt erstellt hat, also diesen kunden aufgerufen hat. Jetzt kann es sein das sich die beiden ihre daten gegenseitig überschreiben.
Was kann man dagegen machen?
Ich habe mir überlegt einen flag zu machen mit "r" (read), also nur lesen erlaubt, und "w" (write), also kann man schreiben, dann noch mit einem timestamp versehen und noch die ID vom benutzer der darauf zugreift, aber was passiert wenn ein benutzer den browser schließt oder das programm stürzt ab?
Man könnte natürlich sagen wenn nach 2 stunden der flag immer noch auf "r" ist, kann man wieder darauf zugreifen, aber das muss doch auch anders gehen! Oder nicht?

ich habe eine mysql datenbank, gibt es eine bessere dafür?

Content-ID: 40732

Url: https://administrator.de/contentid/40732

Ausgedruckt am: 26.11.2024 um 05:11 Uhr

Kaubeu
Kaubeu 22.09.2006 um 21:35:08 Uhr
Goto Top
Hallo,

Du kannst die Tabellen für Lese- und/oder Schreibzugriffe sperren, schau Dir mal die Beschreibung zu LOCK TABLES an: http://dev.mysql.com/doc/refman/5.1/de/lock-tables.html
Biber
Biber 22.09.2006 um 23:39:39 Uhr
Goto Top
Moin, Master-F,

Deine Vorüberlegungen halte ich für eine sehr gute Beschreibung der RecordLocking-Problematik.
Um die geht es ja - ein Table-Lock hilft hier (beim Ändern eines Kundensatzes) nun wirklich nicht. So etwas braucht man/frau bei Massen-Updates oder wenn eine komplexe (und daher längerwierige) Auswertung gefahren wird. Dann muss verhindert werden, dass zwischendurch Sätze geändert werden.

Der Ansatz
Ich habe mir überlegt einen flag zu machen mit "r" (read), also nur lesen erlaubt, und "w" (write), also kann man schreiben,
dann noch mit einem timestamp versehen und noch die ID vom benutzer der darauf zugreift,....
... vergiss es. Nicht praktikabel - den Du nutzt ja nach wie vor die Strategie des Persistierens, der Schreiben in DB-Felder. Und hast daher auch dort "Kollisionen" und die von Dir beschriebenen Flag-Leichen, wenn ein DAU-User mal einfach die ganze Applikation schließt oder die Connection abbricht oder der PC wegen Feierabend ausgeschaltet wird..

Die Strategie, die ich immer angewendet habe (ich beschreibe der einfachsten Fall: EIN Datensatz EINER Tabelle):

- den Datensatz lesen und anzeigen...alle Feld-Werte zu diesem Zeitpunkt identisch mit dem Zustand in der DB.

- vom angezeigten DS eine Eins-zu-Eins-Kopie speichern.
Als Clone des Records, in einem Array, schlimmstenfalls Feld für Feld in einzelnen Variablen.Je nachdem, was die verwendete Sprache hergibt.

- wenn der Benutzer zu erkennen gibt, dass er etwas davon bearbeiten/editieren will oder einzelne Felder ändert..
.... dann ist es egal - auf seinem Bildschirm darf er tun, was er will.

- wenn er allerdings "Speichern" oder "OK" sagt oder auf einen anderen Satz wechseln will, dann:
Vergleichen, ob das, was GELESEN wurde, immer noch mit dem Inhalt der DB übereinstimmt.

- Wenn nein: "Der Datensatz wurde inzwischen geändert. Datensatz neu lesen oder mit den Werten auf dem Bildschirm überschreiben?"

- Wenn es übereinstimmt, dann Datensatz speichern (bzw. falls die verwendete DB es anbietet zuvor RecordLock oder PageLock), DS neu lesen, DS anzeigen

[Variation des Themas wäre: In jeder, aber auch jeder Tabelle 2 oder 3 Felder mitzuschleppen: UserId(letzterÄnderer); TimeStamp(letzteAenderung),Prozess/App letzte Änderung) und diese Werte als Kriterium zu nehmen. Ist einfach, aber frisst natrlich richtig Ressourcen.

Falls Dir das beides zu aufwändig erscheint: die dritte Alternative wäre die Strategie:
"Wer zuletzt schreibt, hat immer Recht, alle Zwischenänderungen werden unbesehen und unbemerkt überschrieben."

Gruß
Biber
Master-F
Master-F 24.09.2006 um 11:12:49 Uhr
Goto Top
Also das hört sich sehr gut an aber ich habe die letzten beiden schritte nicht verstanden könntest du die noch mal genauer beschreiben?

Danke schön schon mal
gruß Master-F
Guenni
Guenni 24.09.2006 um 20:44:57 Uhr
Goto Top
@Master-F

Hi,

Biber's Variante liest sich zunächst mal logisch.

Aber gehen wir im Geiste dein Szenario mal durch:

Kunde bekommt drei Angebote:
Variante 1
Variante 2
Variante 3

Er entscheidet sich für Variante 2, Datensatz wird gespeichert,
Auftrag weitergegeben o.ä., fertig.

Kunde ruft an: Sorry, will doch Variante 3.

Meier setzt sich an den PC, um den Auftrag zu überarbeiten.

Er lädt den Datensatz, überarbeitet ihn.

Während Meier den Datensatz bearbeitet, ruft der Kunde wieder an,
und will nun doch Variante 1 haben.

Müller hat das Gespräch entgegen genommen und bearbeitet nun
auch den gleichen Datensatz.

Jetzt kommt Biber's Vorschlag:

Wenn Meier(oder Müller) auf Speichern/Ändern "klickt", so soll:

- der Datensatz nochmal abgerufen werden
- der Datensatz mit der zuvor geholten Kopie verglichen werden,
ob sich zwischendurch was geändert hat.

- Wenn nein, soll die Änderung durchgeführt werden.

Wenn aber ja, was dann ....?

Welche Version ist denn nun die Neueste/Gewollte? Die von Müller, weil
er als letzter den Datensatz bearbeitet hat?

Oder doch die von Meier, weil er eher fertig war als Müller, obwohl
Müller den zweiten Anruf entgegennahm?

Nächste Frage: Der Mitarbeiter bekommt eine Meldung, dass der
Datensatz zwischenzeitlich überarbeitet wurde. Was macht der Mitarbeiter?
Rumtelefonieren? Oder bricht er ab, obwohl er die neueste Info vom
Kunden hat? Speichert er ab, obwohl seine Info älter ist?

Das Sperren der Tabelle ist, meiner Meinung nach, die bessere Alternative.

Zusätzlich würde ich Biber's Vorschlag aufnehmen, entsprechende Felder in
der Tabelle zu führen, wer letzte Änderungen wann durchgeführt hat.

Dann kann der Mitarbeiter, der den Datensatz bearbeiten will, gezielt
Rücksprache halten.

Grüße
Günni
Biber
Biber 25.09.2006 um 08:21:42 Uhr
Goto Top
Jein, Günni,

wie oben geschrieben - ich habe es durchaus so wie oben skizziert praktiziert.

Auch sogar mit einer Drei-Zustände-Anzeige zur Entscheidung durch den Benutzer
(Zustand "alter" Datensatz in der Tabelle; Zustand durch Änderung durch anderen Mitarbeiter; Zustand durch eigene Änderung.)

Die Frage hierbei ist nur, ob die MA diese Differenziertheit wollen.
Dann - muss man/frau ehrlicherweise dazusagen: wenn zwei MA am selben Kunden, an der selben Artikelnummer oder ähnliches rumändern, dann deutet das auf ein organisatorisches Problem hin. Sollte normalerweise nicht vorkommen, dass für DS-Änderungen -d.h. i.d.R. Stammdaten- mehrere MA zuständig sind.
Bei Neueingaben (=i.d.R. Bewegungs/Buchungsdaten) habe ich ja das Problem gar nicht.

Von der Implementierung jedenfalls lässt sich diese Strategie händeln.
Allerdings reicht nach meinen Erfahrungen durchaus die Rückmeldung "Der Datensatz wurde inzwischen geändert. Wollen Sie trotzdem Ihre Änderungen speichern?".
In 95% der Fälle ist die Antwort "Ja" (bedeutet im ganzen Satz: Was ich eingebe, ist gut und wahr und richtig - egal, welche Nase da zwischendurch meinte, schlauer zu sein als ich.."

[Edit] und dieses hier:
Das Sperren der Tabelle ist, meiner Meinung nach, die bessere Alternative.
Tja, dann sperr doch mal eine Tabelle mit 4 Mio Artikelstammdaten, weil einer der MA einen Satz ändern will... face-wink
[/Edit]

Gruß
Biber
Master-F
Master-F 25.09.2006 um 08:48:14 Uhr
Goto Top
@Biber

aber wenn man sich nach deinem vorschlag orientiert dann kann man doch gleich dem letzten der eingetragen hat rechtgeben!!! das will ich nicht.

ich verstehe nicht wie das andere hinbekommen das dort angezeigt wird das der datensatz immoment benutzt wird, bitte versuchen sie es später noch mal, oder so was.
benutzen die andere datenbanken oder so?

@günni

wenn einer eine tabelle sperren können die anderen noch die tabelle lesen? aber was ist wenn z.B. der rechner abstürzt oder so etwas, bleibt die tabelle dann für immer geschlossen?

Gruß Master-F
Biber
Biber 25.09.2006 um 09:31:13 Uhr
Goto Top
aber was ist wenn z.B. der rechner abstürzt oder so etwas, bleibt die tabelle dann für immer geschlossen?

Nein. Sowohl File/Table-Locking wie auch das satzweise Sperren (RecordLocking) wird NICHT persistiert - sondern nur über eine Sperrung eines Teilbereichs eines physisch vorhandenen Files abgebildet. Und da es immer "von einem Benutzer" bzw. "von einem Prozess" gesperrt ist, gilt das nur solange der Prozess noch "lebt".

Nur ganz, ganz dumme Datenbanken hatten tatsächlich mal eine DB-Sperrung durch Anlegen eines 0-Byte-Files mit einem Namen wie Database.loc (für Locked) implementiert.
Mit genau dem Effekt, dass bei einem Absturz niemand mehr in die DB konnte.

Und die Meldung "Dieser Datensatz wird gerade bearbeitet: Das ist auch eine benutzerlesbare Übersetzung der Aussage: "Dieser Datensatz ist gesperrt; jemand macht gerade ein RekordLocking."
Diese Meldung kann aber nur kommen, wenn der DS länger gesperrt, d.h. zu Beginn der Bearbeitung gesperrt wird, bis der MA endlich nach 3 Telefonaten und seiner Mittagspause irgendwann "Speichern" oder "Abbruch" drückt. Ist IMHO nicht erstrebenswert.
Bei der Strategie oben ist der Datensatz ebeb nur gesperrt im Moment des Speicherns - der Nachteil dabei ist aber, dass angezeigter und zu überschreibender Satz nicht mehr identisch sein könnten.

Und zu Deinem Einwand ..."dann wird doch dem letzten Änderer immer Recht gegeben.."
Ja. Siehe oben: organisatorisch sollte auch geregelt sein, dass jeder MA für bestimmte Sätze (Artikel-, Kunden-, Auftragsnummernkreise...) zuständig ist und auch geregelt sein, dass nicht zwei Mitarbeiter gleichzeitig damit ihre Zeit verbringen, die Telefaxnummern vom Kunden Karl-Heinz zu überprüfen und zu aktualisieren.

Gruß
Biber