mmofacts.com

Einfaches Locking mit MySQL

gepostet vor 19 Jahre, 1 Monat von Krisch
Hallo,

ich bastel gerade an einem Projekt bei dem es wichtig ist, dass einige Aufgaben nicht parallel verarbeitet werden. Da diese Sachen immer möglichst aktuell sein sollen, ist ein CronJob eher unpraktisch (wird aber zur Unterstützung dazukommen).

Also hab ich mir überlegt, dass ich in einer MySQL Tabelle speichere welche Aufgaben zu erledigen sind und ob sie im Moment ausgeführt werden. Während der Verarbeitung wird die Startzeit als Timestamp gespeichert, am Ende der Verarbeitung wird der Timestamp auf 0 gesetzt.

Also wird beim Skriptaufruf ein Update auf die Tabelle gemacht (mit Timestamp <= time() - Zeitgrenze) und dann mit mysql_affected_rows geprüft, ob die Aufgabe gelockt ist.


Kann ich das so machen? Oder kann es Probleme geben?

Geht es besser? (nur mit PHP, Java hab ich erstmal verschoben)
gepostet vor 19 Jahre, 1 Monat von None
Ich sehe da keine Probleme...

Allerdings habe ich für solche "Events" meinen Java Hintergrundprozess. Hielt ich für eleganter und geschickter als alles mit PHP zu machen und die Umwege zu gehen. Habe allerdings auch ca. 25 verschiedene Events, bei denen zum Teil bis zu 16 DB-Abfragen gemacht werden müssen.
gepostet vor 19 Jahre, 1 Monat von schokofreak
- es können 2 Prozesse parallel einen Timestamp schreiben... ohne zu merken, dass das sonst noch wer macht
- ein Prozess der abschmiert generiert einen Endlos- Lock

auf KEINEN FALL so machen!
gepostet vor 19 Jahre, 1 Monat von poncho
Original von schokofreak
- es können 2 Prozesse parallel einen Timestamp schreiben... ohne zu merken, dass das sonst noch wer macht
- ein Prozess der abschmiert generiert einen Endlos- Lock

auf KEINEN FALL so machen!

Da würde ich nicht zustimmen.

Es kann nur ein Prozess einen Lock setzen, denn die Datenbank führt das nicht wirklich parallel aus.
Außerdem werden Locks IMO nach dem schließen der Verbindung, was beim Abstürz des Prozess' der Fall wäre, wieder entriegelt.
gepostet vor 19 Jahre, 1 Monat von schokofreak
Original von poncho
Original von schokofreak
- es können 2 Prozesse parallel einen Timestamp schreiben... ohne zu merken, dass das sonst noch wer macht
- ein Prozess der abschmiert generiert einen Endlos- Lock

auf KEINEN FALL so machen!

Da würde ich nicht zustimmen.

Es kann nur ein Prozess einen Lock setzen, denn die Datenbank führt das nicht wirklich parallel aus.
Außerdem werden Locks IMO nach dem schließen der Verbindung, was beim Abstürz des Prozess' der Fall wäre, wieder entriegelt.

Lustig ist nur, dass da nicht von Lock table gesprochen wird in diesem Thema...
Sondern von einem Feld mit einem TimeStamp gefüllt... solange timestamp da warten alle.
Das hat nix mit dem Table- Lock zu tun, wie du meinst.
Und selbst ein Table Lock funktioniert nich teinfach so gut wie du da schreibst.
gepostet vor 19 Jahre, 1 Monat von TheUndeadable
Ich persönlich würde mich nur auf Semaphoren oder File-Locking verlassen. Das BS kümmert sich auch um die Freigabe, falls ein Skript abschmieren sollte. Bei den Snippets wirst du gleich meine Klasse finden, die das File-Locking abkapselt.
gepostet vor 19 Jahre, 1 Monat von Krisch
Äh, ich blick jetzt nicht mehr durch bei File-, Table- und meinem Locking.

Die Frage ist eigentlich nur ob MySQL parallele Updates auf eine Tabellen Zeile erlaubt. Also das ein zweites Update den Wert für den WHERE Teil überprüft, bevor das erste Update den Wert ändert:

1. Update sieht Timestamp ist veraltet
2. Update sieht Timestamp ist veraltet
1. Update ändert den Wert
2. Update ändert den Wert

Bei einem Fehler wird der Lock automatisch nach einer Zeitspanne freigegeben, falls das nicht klar war.

@TheUndeadable: Was sind Semaphoren? Und welche Snippets meinst du?
gepostet vor 19 Jahre, 1 Monat von TheUndeadable
Was du machst ist manuelles Locking und nicht empfehlenswert, da jedes Betriebssystem/Datenbank selbst Mechanismen zur Verfügung stellt, die ein Locking ermöglichen.

MySQL hat Table-Locking (Lock auf eine Tabelle), viele Datenbanken haben Row-Locking (Lock auf eine bestimmte Zeile)

Jedes Betriebssystem stellt selbst noch verschiedene Locking-Funktionen zur Verfügung. Ein Beispiel wäre File-Locking. Dabei wird eine Dummy-Datei genutzt, auf die ein Lock gesetzt wird. Dieses Lock kann manuell wieder zurückgenommen werden oder wird vom BS bei Beendigung des Prozesses automatisch wieder freigegeben.

Semaphoren und Mutexe sind vom BS zur Verfügung gestellte Objekte, die sich eigentlich für die Synchronsierung von Programmteilen eignen. Leider ist die Ansteuerung dieser unter allen Betriebssystemen nicht sonderlich einheitlich.

Informationen zur Synchronisierung:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/semaphore_objects.asp (Semaphore)
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/mutex_objects.asp (Mutexe)
> Bei einem Fehler wird der Lock automatisch nach einer Zeitspanne freigegeben, falls das nicht klar war.

Wie groß wäre dein Timeout? 10 Sekunden, 30 Sekunden? Was machst du, wenn ein Skript tatsächlich mal länder als 30 Sekunden brauchen sollte. Riskierst du dann eine Korrumption der Datenbank?

EDIT:
Achso, zur Snippets-DB: http://snippets.galaxy-news.de Einfach mit deinen Forendaten einloggen (falls du Entwickler bist)
gepostet vor 19 Jahre, 1 Monat von Krisch
Table-Locking ist eine gute Idee, aber ich glaube, dass das bei mir nicht so gut wäre.

Das Skript das nicht parallel laufen darf, nimmt immer einen Teil der Tabelle und verarbeitet ihn. Dieser Teil kann nur von diesem Skript verändert werden, während der Rest weiterhin parallel geändert werden darf.
Wenn ich die Tabelle locke, können die anderen Skripte nicht weiterarbeiten. Da muss ich erst in der Praxis testen, was besser läuft.

Und Row-Locking ist nicht möglich, weil ich dann schlecht nachvollziehen kann, ob das Skript nicht läuft oder neue Zeilen zum Verarbeiten freigegeben wurden.


Aber das mit dem Timeout muss ich mir nochmal überlegen.

(Bisher bin ich leider nicht als Entwickler eingestuft worden ..)
gepostet vor 19 Jahre, 1 Monat von TheUndeadable
Dann nutze File-Locking.
Erzeuge bestimmte Dateien für bestimmte Aktionen und locke sie mit diesem (flock heißt der Befehl unter PHP). Damit garantierst du, dass diese Aktion nur von einem Skript gleichzeitig durchgeführt wird.

Ein Tutorial was ich mal geschrieben hatte: http://browsergames.net/thread.php?threadid=708&sid=

http://nopaste.php-q.net/159334 <- Die Klasse

BZW: Arbeite dich evtl mal in Transaktionen ein. Da kannst du eine komplette Aktion in einem Rutsch und atomar durchführen.

Auf diese Diskussion antworten