Record Locking Problem

Nein, das Problem ist ja er kann immer alle Datensätze lesen und das Schreiben wird keine Fehlermeldung werfen sondern einfach warten, bis der Datensatz wieder freigegeben wird, und das ist der Knackpunkt.
 
Ich danke euch für eure vielen Antworten!
Gelöst scheint das Problem wohl nicht ganz zu sein.
Ich werde eine provisorische Lösung vornehmen:
Ich füge eine Spalte namens author o. ä. hinzu, die den Benutzernamen des Verwalters beinhaltet. Nur dieser kann dann noch den Auftrag einsehen, editieren, ... .
Die Auftragsverwaltung läuft dann halt ähnlich wie beim eMail abholen: man gibt bekommt zwischen 3-7 neue Aufträge per klick hinzu, um die man sich kümmeren muss... wenn die abgearbeitet sind, fordert man halt die nächsten an ...

Ich lasse dieses Topic trotzdem noch offen, da eine Lösung bisher ja noch nicht gefunden ist und ich das Programm noch nicht abgeben musss. Sollte sich die Lösung noch finden, kann ich versuchen so weit wie möglich diese im Programm zu berücksichtigen...

Vielen Dank noch einmal,

Marcel
 
Hallo tobias_petri,

ich habe mit mysql noch nicht viel praktische Erfahrung sammeln dürfen,
aber mit anderen Datenbanken schon: z. B. Oracel.

Wenn in dem oben genannten Beispiel mit Auftragslisten gearbeitet wird, kann man das doch folgendermassen realisieren:

1. Lesen der zu bearbeitenden Daten ohne Lock (von mehreren Anwendern gleichzeitig)
2. Wenn ein Bearbeiter einen Datensatz aus seiner Liste bearbeiten will, werden
die Daten noch einmal von der Datenbank nachgelesen. Jetzt erfolgt ein
SELECT … FOR UPDATE mit dem eindeutigen Schlüssel. Dadurch sollte der Satz
für andere gesperrt werden. Ist der Satz schon bei jemand anders in Bearbeitung
erscheint die Meldung: Satz wird aktuell von jemand anders bearbeitet.

Wenn das nicht funktionert, stimmt die Dokumentation von mysql nicht:

SELECT … FROM … FOR UPDATE setzt exklusive Next-Key-Sperren auf alle Indexeinträge, die der Lesevorgang findet.

Im Grunde genommen ist dieser Ansatz schon weitestgehend richtig, allerdings liefert selbst SELECT ... FOR UPDATE nur einen Schnappschuss der Datenbank, um wirklich eine Lesesperre zu erhalten müsste man laut MySQL-4.1-Refernzhandbuch den Befehl SELECT ... LOCK IN SHARE MODE verwenden.

Hier einfach mal der Abschnitt aus dem Referenzhandbuch:
8.5.8.2. Lesevorgänge sperren
Unter manchen Umständen ist Konsistentes Lesen nicht wünschenswert. Angenommen, Sie wollen eine neue Zeile in die Tabelle kind einfügen und dabei sicherstellen, dass das Kind bereits Eltern in der Tabelle eltern hat.

Wenn Sie Konsistentes Lesen benutzen, um die Tabelle eltern zu lesen und in der Tat die Eltern des Kindes in der Tabelle sehen, können Sie dann sicher die Kind-Zeile zur Tabelle kind hinzufügen? Nein, denn es kann sein, dass zwischenzeitlich jemand anderes die Eltern-Zeile aus der Tabelle eltern gelöscht hat und Sie das nicht sehen.

Die Lösung besteht darin, das SELECT im Sperrmodus durchzuführen. LOCK IN SHARE MODE.

SELECT * FROM eltern WHERE NAME = 'Hinz' LOCK IN SHARE MODE;

Wenn Sie ein Lesen im Share-Modus durchführen, heißt das, dass die letzten verfügbaren Daten gelesen werden und eine Shared-Modus-Sperre auf die Zeile gesetzt wird, die gelesen wird. Wenn die letzten Daten zu einer noch nicht abgeschlossenen Transaktion eines anderen Benutzers gehören, wird gewartet, bis die Transaktion abgeschlossen (committed) ist. Eine Shared-Modus-Sperre verhindert, dass andere die Zeile aktualisieren oder löschen, die gerade gelesen wurde. Nachdem festgestellt wurde, dass die obige Anfrage die Eltern 'Hinr' zurückgibt, kann das Kind sicher zur Tabelle kind hinzugefügt und die Transaktion abgeschlossen werden. Dieses Beispiel zeigt, wie Sie in Ihren Applikations-Code referentielle Integrität integrieren können.

Sehen wir uns ein weiteres Beispiel an. Wir haben ein ganzzahliges Zählerfeld in einer Tabelle kind_codes, was benutzt wird, um jedem Kinde, das wir der Tabelle kind hinzufügen, eine eindeutige Kennung zuzuweisen. Es ist offensichtlich, dass Konsistentes Lesen oder Shared-Modus-Lesen kein geeignetes Mittel ist, um den aktuellen Wert des Zählers zu ermitteln, weil nämlich zwei Benutzer der Datenbank denselben Wert des Zählers sehen können und wir daher einen Fehler wegen doppelter Schlüsseleinträge erhalten, wenn wir zwei Kinder mit derselben Kennung in die Tabelle einfügen.

In diesem Fall gibt es zwei geeignete Möglichkeiten, das Lesen und Heraufzählen des Zählers zu implementieren: (1) Zuerst den Zähler um eins erhöhen und erst danach lesen. (2) Zuerst den Zähler im Sperr-Modus FOR UPDATE lesen und danach heraufzählen:

SELECT COUNTER_FIELD FROM kind_codes FOR UPDATE;
UPDATE kind_codes SET COUNTER_FIELD = COUNTER_FIELD + 1;

SELECT ... FOR UPDATE liest die letzten verfügbaren Daten und setzt exklusive Sperren auf jede Zeile, die es liest. Daher setzt es dieselben Sperren, die ein gesuchtes SQL-UPDATE auf die Zeilen setzen würde.

Nur als Hinweis selbst wenn man ein Flag verwendet, kann man nicht sicher sein, dass ein anderer User in der Millisekunde vor dem Flag setzen den Datensatz geändert hat.

Wenn Du mehr wissen willst lad Dir doch einfach das MySQL-Referenzhandbuch herunter und lies Dir den Abschnitt "8.5. InnoDB-Tabellen" durch.

Sehr informativ ist auch diese Seite http://www.innodb.com

Beste Grüße
 

Neue Beiträge

Zurück