Parallele Zugriffe
am 27.02.2005 16:58:50 von gewinn
Guten Tag!
Ich habe eine größere Tabelle mit Adressen.
Die Tabelle wird von mehreren Rechnern parallel bearbeitet,
d.h. jeder Bearbeiter soll einen Datensatz mit einer Adresse bekommen,
diesen bearbeiten und dann die nächste zugewiesen bekommen.
Problem: Wie schaffe ich es, dass zwei Bearbeiter nicht die gleiche
Adresse bekommen? Kann man eine Datensatz auswählen und direkt einen
Wert im Satz ändern (Bearbeitet FLAG o.ä.) ?
Ablauf: Jeweils ein SELECT mit LIMIT 1 von allen Adressen, die noch
nicht das bearbeitet Flag gesetzt haben. Wenn fertig bearbeitet, wird
das Flag gesetzt.
Gruss
Lars Höhmann
Re: Parallele Zugriffe
am 27.02.2005 21:05:03 von Abitos Schrelb
Lars Höhmann wrote:
> Guten Tag!
>
> Ich habe eine größere Tabelle mit Adressen.
> Die Tabelle wird von mehreren Rechnern parallel bearbeitet,
> d.h. jeder Bearbeiter soll einen Datensatz mit einer Adresse bekommen,
> diesen bearbeiten und dann die nächste zugewiesen bekommen.
> Problem: Wie schaffe ich es, dass zwei Bearbeiter nicht die gleiche
> Adresse bekommen? Kann man eine Datensatz auswählen und direkt einen
> Wert im Satz ändern (Bearbeitet FLAG o.ä.) ?
Mir fallen da konkret folgende Stichwörter ein:
- MySQL InnoDB -> Bietet Transactions
- Transactions
- Locking
Ich hoffe, dass das weiterhilft.
mfg Tobias
> Gruss
> Lars Höhmann
--
Alle eMails an die genannte Adresse landen in /dev/null
Kontaktinfos auf www.schrelb.de
Re: Parallele Zugriffe
am 28.02.2005 21:06:53 von Axel Schwenke
Abitos Schrelb wrote:
> Lars Höhmann wrote:
>>
>> Ich habe eine größere Tabelle mit Adressen.
>> Die Tabelle wird von mehreren Rechnern parallel bearbeitet,
>> d.h. jeder Bearbeiter soll einen Datensatz mit einer Adresse bekommen,
>> diesen bearbeiten und dann die nächste zugewiesen bekommen.
>> Problem: Wie schaffe ich es, dass zwei Bearbeiter nicht die gleiche
>> Adresse bekommen? Kann man eine Datensatz auswählen und direkt einen
>> Wert im Satz ändern (Bearbeitet FLAG o.ä.) ?
>
> Mir fallen da konkret folgende Stichwörter ein:
> - MySQL InnoDB -> Bietet Transactions
> - Transactions
> - Locking
Aaargh! Bloß nicht!
Abitos(seltsamer Name?) hat schon vollkommen richtig getippt: ein Flag
mit der Bedeutung "dieser Datensatz wird seit ... von ... bearbeitet"
und ein bisschen Logik in der Applikation sind hier die Lösung.
Google weiß (viel) mehr. Stichwort: "optimistic locking"
XL
Re: Parallele Zugriffe
am 01.03.2005 07:37:29 von do.not.REMOVETHAT
Lars Höhmann schrieb:
> Wie schaffe ich es, dass zwei Bearbeiter nicht die gleiche
> Adresse bekommen?
Das ist schwer. Das kann man nicht wirklich sicher verhindern ohne dabei
Datensätze "für immer" zu sperren.
> Kann man eine Datensatz auswählen und direkt einen
> Wert im Satz ändern (Bearbeitet FLAG o.ä.) ?
Ja. So ist richtig. Aber besser: nicht boolean Flag "Wird bearbeitet"
sondern Zeitfeld "wird bearbeitet seit". Wenn es dann seit 2 Stunden
bearbeitet wird ohne dass es gespeichert wurde kannst Du es wieder
aufheben.
> Ablauf: Jeweils ein SELECT mit LIMIT 1 von allen Adressen, die noch
> nicht das bearbeitet Flag gesetzt haben.
Nein. "...die das Fertig-bearbeitet-Flag noch nicht haben und auch noch
keinen Zeitpunkt in wird-bearbeitet-seit stehen haben". Beim Aufrufen
wird dann ein Zeitpunkt in wird-bearbeitet-seit geschrieben. Beim
speichern wird der wieder gelöscht und...
> Wenn fertig bearbeitet, wird
> das Flag gesetzt.
Ja genau.
Und Wichtig: Vergiss die Locking-Mechanismen der DBMSse.
Grüße, Matthias
--
"Hurd will be out in a year"
(Linus Benedict Torvalds, 5. Oktober 1991)
http://groups-beta.google.com/group/comp.os.minix/msg/2194d2 53268b0a1b
Re: Parallele Zugriffe
am 01.03.2005 13:26:43 von gewinn
"Matthias P. Wuerfl" wrote in message news:<38ih39F5nifsfU1@individual.net>...
> > Ablauf: Jeweils ein SELECT mit LIMIT 1 von allen Adressen, die noch
> > nicht das bearbeitet Flag gesetzt haben.
>
> Nein. "...die das Fertig-bearbeitet-Flag noch nicht haben und auch noch
> keinen Zeitpunkt in wird-bearbeitet-seit stehen haben". Beim Aufrufen
> wird dann ein Zeitpunkt in wird-bearbeitet-seit geschrieben. Beim
> speichern wird der wieder gelöscht und...
Kann ich denn "direkt" nach dem Lesen dieses FLAG mit timestamp setzen
(am besten lesen und direkt schreiben) ?
Gruss
Lars Höhmann
Re: Parallele Zugriffe
am 01.03.2005 14:55:28 von do.not.REMOVETHAT
Lars H?hmann schrieb:
> Kann ich denn "direkt" nach dem Lesen dieses FLAG mit timestamp setzen
> (am besten lesen und direkt schreiben) ?
Vor!
Mit einem "where" auf PK *und* das Flag. Wenn mysql_affected_rows(?)
dann 1 ist machst Du einen select für das Bearbeiten. Wenn 0, dann
jemand anderes zuerst da.
Nur wenn das Flag-Setzen-Update das Flag im "where" hat und Du die
Anzahl der veränderten Reihen überprüfst, verhinderst Du
Race-Conditions, weil nur so Test und Update atomar auf einmal sind.
Grüße, Matthias
--
"Hurd will be out in a year"
(Linus Benedict Torvalds, 5. Oktober 1991)
http://groups-beta.google.com/group/comp.os.minix/msg/2194d2 53268b0a1b
Re: Parallele Zugriffe
am 02.03.2005 15:39:03 von Markus Malkusch
Matthias P. Wuerfl:
> Und Wichtig: Vergiss die Locking-Mechanismen der DBMSse.
Dann wird's aber schwierig (sofern man nicht auf andere Sperrmechanismen
ausweicht) sich vor Raceconditions zu schützen. Wenn ich das richtig
blicke, muss man vor dem Setzen des Flags/Zeit ein Select ausführen. D.h.
es besteht die Gefahr, dass mehrere den selben Datensatz erhalten.
--
- Whoisabfrage
Re: Parallele Zugriffe
am 02.03.2005 16:02:15 von do.not.REMOVETHAT
Markus Malkusch schrieb:
> Dann wird's aber schwierig (sofern man nicht auf andere Sperrmechanismen
> ausweicht) sich vor Raceconditions zu schützen.
update table set editflag = true where id= $id and editflag = false.
if(mysql_affected_rows()!=1) echo "Datensatz in Benutzung".
<38jaohF5msjf7U1@individual.net>
Grüße, Matthias
Re: Parallele Zugriffe
am 02.03.2005 16:11:08 von Markus Malkusch
Matthias P. Wuerfl:
> update table set editflag = true where id= $id and editflag = false.
Dann hab' ich wohl was falsch verstanden. Ich habe das OP so verstanden,
dass $id erst anhand der unbearbeiteten ermittelt werden muss. Aber wenn
$id ohne SELECT bekannt ist, dann ist das natürlich ohne Sperren atomar
lösbar.
--
- Kontonummerprüfung mit PHP
Re: Parallele Zugriffe
am 02.03.2005 16:25:14 von do.not.REMOVETHAT
Markus Malkusch schrieb:
> Dann hab' ich wohl was falsch verstanden. Ich habe das OP so verstanden,
> dass $id erst anhand der unbearbeiteten ermittelt werden muss. Aber wenn
> $id ohne SELECT bekannt ist, dann ist das natürlich ohne Sperren atomar
> lösbar.
Das herausfinden der ID ist nicht das Problem. Das Problem ist das
"Sperren". Man muss "schauen, ob schon gesperrt ist" und "für mich
sperren" *gleichzeitig* machen. *Was* man dann gesperrt hat ist eagl.
Die ID kannst Du ruhig kurz vorher herausgefunden haben. In dem Moment
in dem Du sperrt überprüfst Du ja gleichzeitig noch mal indem Du sagt
"sperre mir alle DS mit der ID X, die noch nicht gesperrt sind" und dann
schaust, wieviele das sind: Einer oder keiner.
Grüße, Matthias
--
"Hurd will be out in a year"
(Linus Benedict Torvalds, 5. Oktober 1991)
http://groups-beta.google.com/group/comp.os.minix/msg/2194d2 53268b0a1b
Re: Parallele Zugriffe
am 02.03.2005 16:41:01 von Markus Malkusch
Matthias P. Wuerfl:
> Die ID kannst Du ruhig kurz vorher herausgefunden haben. In dem Moment
> in dem Du sperrt überprüfst Du ja gleichzeitig noch mal
Schön, und wenn Dein UPDATE scheiterte heißt das dann dass die ID jetzt doch
von einem anderen Prozess gesperrt wurde? Und selbst wenn dem so ist, was
passiert danach? Holst Du auf dieselbe Art und Weise die nächste potentiell
freie ID? Das wäre dann ein nichtdeterministischer Algorithmus, den man mit
wenigst Aufwand¹ vermeiden kann.
[1]: Damit meine ich die zwei Zeilen zum Sperren und Entsperren. Mir ist
schon klar, dass das Sperren selbst nicht billig ist.
--
- Whoisabfrage
Re: Parallele Zugriffe
am 02.03.2005 16:43:09 von Markus Malkusch
Matthias P. Wuerfl:
> Die ID kannst Du ruhig kurz vorher herausgefunden haben. In dem Moment
> in dem Du sperrt überprüfst Du ja gleichzeitig noch mal
Schön, und wenn Dein UPDATE scheiterte heißt das dann dass die ID jetzt doch
von einem anderen Prozess /gesperrt/ wurde? Und selbst wenn dem so ist, was
passiert danach? Holst Du auf dieselbe Art und Weise die nächste potentiell
freie ID? Du magst also nichtdeterministische Algorithmen?
Re: Parallele Zugriffe
am 02.03.2005 16:45:20 von Axel Schwenke
Markus Malkusch wrote:
> Matthias P. Wuerfl:
>
>> Und Wichtig: Vergiss die Locking-Mechanismen der DBMSse.
>
> Dann wird's aber schwierig (sofern man nicht auf andere Sperrmechanismen
> ausweicht) sich vor Raceconditions zu schützen. Wenn ich das richtig
> blicke, muss man vor dem Setzen des Flags/Zeit ein Select ausführen.
Nope. Gesetzt den Fall, das Flag ist eine CHAR() Spalte mit dem Namen
des Bearbeiters. Ein "freier" Datensatz hat da NULL drin stehen. Den
Timestamp realisiert man am besten durch eine TIMESTAMP Spalte.
UPDATE stammdaten
SET bearbeiter = $current_user
WHERE id = $id
AND (bearbeiter IS NULL OR zeitstempel < NOW() - INTERVAL $timeout)
if ($affected_rows == 1) {
#jetzt ist das mein Datensatz
} else {
#der gehört jemand anderem
}
ABER: das ist kein "optimistic locking"
Optimistisches Locken verwendet einen Versionszähler für Datensätze.
Wenn man einen Datensatz bearbeiten will, selektiert man alle zu
ändernden Daten und den Zähler. Beim Zurückschreiben (UPDATE) wird der
Zähler erhöht und in das WHERE kommt ein 'AND zaehler=$alter_wert'.
Dieses UPDATE schlägt genau dann fehl, wenn zwischenzeitlich jemand
anderes auf diesen Datensatz geschrieben hat. Dann liest man Zähler
und Daten erneut aus und kann so z.B. auch feststellen, ob beide
Änderungen verträglich sind (z.B. könnte eine Änderung die Adresse
und die andere die Telefonnummer betreffen). Sonst läßt man den
Nutzer entscheiden.
Vorteile gegenüber einem Lock-Flag: es wird nur einmal auf die Tabelle
geschrieben. Es gibt keine Timeouts.
XL
Re: Parallele Zugriffe
am 02.03.2005 16:48:03 von do.not.REMOVETHAT
Markus Malkusch schrieb:
> Schön, und wenn Dein UPDATE scheiterte
s/scheitern/keinen Datensatz veränderte
> heißt das dann dass die ID jetzt doch
> von einem anderen Prozess /gesperrt/ wurde?
Ja.
> Und selbst wenn dem so ist, was
> passiert danach?
Was Du willst.
> Holst Du auf dieselbe Art und Weise die nächste potentiell
> freie ID?
Zum Beispiel.
> Du magst also nichtdeterministische Algorithmen?
Hä?
Es geht darum, dass ein Datensatz nicht doppelt bearbeitet wird. Warum
auch immer. Also muss er "gesperrt" werden. Wie auch immer. Wenn die
Überprüfung auf "ist er gesperrt?" und die Sperrung in 2 Schritten
erfolgt haben wir die Möglichkeit einer Race-Condition. Das wollen wir
verhindern. Um mehr geht es nicht, aber auch nicht um weniger. Wie
willst Du es denn sonst machen?
Grüße, Matthias
--
"Hurd will be out in a year"
(Linus Benedict Torvalds, 5. Oktober 1991)
http://groups-beta.google.com/group/comp.os.minix/msg/2194d2 53268b0a1b
Re: Parallele Zugriffe
am 02.03.2005 17:00:55 von Robert Ernst
Hallo,
Ich habs einmal so gelöst:
Ich hab ein Feld in der Tabelle, indem ein Zahlenwert steht. Bei jedem
Zugriff auf diesen Datensatz wird dieser Wert um eins erhöht.
Nur der User, der den aktuellen Zahlenwert besitzt, darf updaten ;-)
Wenn User A um 16:00 Uhr und User B um 16:01 zugreift, kann nur User B
den Datensatz speichern, User A hat Pech gehabt. Falls User B aber nicht
speichert, hat User A durch erneutes Öffnen des Datensatzes die Chance
mit dem aktuellen Zahlenwert zu speichern.
Der Vorteil ist, dass ich nichts mit einem Timestamp sperren muss, der
Nachteil besteht darin, dass immer nur der letzte zugreifende User
speichern darf.
lg,
Robert
Re: Parallele Zugriffe
am 02.03.2005 17:01:14 von Markus Malkusch
Matthias P. Wuerfl:
>> Du magst also nichtdeterministische Algorithmen?
>
> Hä?
>
> Es geht darum, dass ein Datensatz nicht doppelt bearbeitet wird.
Ich verstehe das OP so, dass außerdem auch ein Datensatz bearbeitet werden
soll. D.h. es soll ein unbearbeiteter ausgewählt werden.
Wenn also Dein UPDATE keinen Datensatz verändert hat, muss mit der selben
Methode ein weiterer Datensatz gesucht werden und wieder ein solches UPDATE
ausgeführt werden. Das Ding kann theoretisch bis in die Ewigkeit laufen
(das meinte ich mit nichtdeterministisch).
> Wie willst Du es denn sonst machen?
Sperren
Unbearbeiteten Eintrag auswählen
Eintrag auf Bearbeiten setzen
Entsperren
Bearbeiten
Eintrag auf nicht Bearbeiten setzen
--
- Kontonummerprüfung mit PHP
Re: Parallele Zugriffe
am 02.03.2005 17:53:16 von do.not.REMOVETHAT
Markus Malkusch schrieb:
> Ich verstehe das OP so, dass außerdem auch ein Datensatz bearbeitet werden
> soll. D.h. es soll ein unbearbeiteter ausgewählt werden.
Den kann man sich ja vorher raussuchen.
> Wenn also Dein UPDATE keinen Datensatz verändert hat, muss mit der selben
> Methode ein weiterer Datensatz gesucht werden und wieder ein solches UPDATE
> ausgeführt werden. Das Ding kann theoretisch bis in die Ewigkeit laufen
> (das meinte ich mit nichtdeterministisch).
Man wird natürlich vorher schon die Bearbeiteten ausschliessen. Das ist
banal.
>>Wie willst Du es denn sonst machen?
>
>
> Sperren
Wie?
> Unbearbeiteten Eintrag auswählen
Wie?
> Eintrag auf Bearbeiten setzen
Wie? Und woher weisst Du dass seit dem Überprufen nix passiert ist?
> Entsperren
Wie?
> Bearbeiten
> Eintrag auf nicht Bearbeiten setzen
Ich glaube wenn Du mir den Rest erklärst kann ich mir die Beiden dann
zusammenreimen :-)
Grüße, Matthias
--
"Hurd will be out in a year"
(Linus Benedict Torvalds, 5. Oktober 1991)
http://groups-beta.google.com/group/comp.os.minix/msg/2194d2 53268b0a1b
Re: Parallele Zugriffe
am 02.03.2005 17:55:31 von do.not.REMOVETHAT
Axel Schwenke schrieb:
> ABER: das ist kein "optimistic locking"
Wollte der OP ja auch nicht, oder?
Re: Parallele Zugriffe
am 02.03.2005 17:57:53 von do.not.REMOVETHAT
Robert Ernst schrieb:
> der Nachteil besteht darin, dass immer nur der letzte zugreifende User
> speichern darf.
Genau das will der OP verhindern, oder?
Re: Parallele Zugriffe
am 02.03.2005 18:11:17 von Markus Malkusch
Matthias P. Wuerfl:
> Den kann man sich ja vorher raussuchen.
Evtl. verstehen wir das beide unterschiedlich. Ich meine der zu bearbeitende
Eintrag wird zugewiesen. D.h. der User wählt ihn selbst gar nicht aus,
sondern kriegt einfach einen, den er aber 100% alleine bearbeitet.
>> Sperren
>
> Wie?
LOCK TABLES table WRITE
>> Unbearbeiteten Eintrag auswählen
>
> Wie?
SELECT id FROM table
WHERE bearbeitungs_kriterium
AND (edited_sinze IS NULL OR edited_sinze < NOW() - INTERVAL $timeout)
LIMIT 1
>> Eintrag auf Bearbeiten setzen
>
> Wie?
UPDATE table SET edited_sinze = NOW() WHERE id = $id
> Und woher weisst Du dass seit dem Überprufen nix passiert ist?
Das weiß ich von meinem LOCK TABLES.
>> Entsperren
>
> Wie?
UNLOCK TABLES
--
- Whoisabfrage
Re: Parallele Zugriffe
am 02.03.2005 18:22:20 von Markus Malkusch
Markus Malkusch:
> LOCK TABLES table WRITE
[..]
> UNLOCK TABLES
Ich hab' jetzt noch mal in die Doku geguckt. Ich glaube das ist doch nicht
die richtige Art zu sperren, weil die Doku nicht ausdrücklich sagt dass
LOCK TABLES WRITE weitere lesende Threads blockiert.
Ich nimm' mal vorsichtshalber meine Aussage zurück und ersetze das MySQL
Gesperre mit einem PHP-Gesperre (flock oder Semaphore).
--
- Whoisabfrage
Re: Parallele Zugriffe
am 03.03.2005 08:14:53 von do.not.REMOVETHAT
Markus Malkusch schrieb:
>>>Sperren
>>
>>Wie?
>
> LOCK TABLES table WRITE
Die *ganze*Tabelle*? Hm. Das geht natürlich auch. Aber findest Du das
nicht ein bisschen unelegant und mit-Kanonen-auf-Spatzen-geschossen?
LOCK, SELECT, UPDATE, UNLOCK
gegen
SELECT UPDATE (und in seltenen Fällen eine Wiederholung dessen)
Ich meine: Es ist sinniger, minimalinvasiv in die Datenbank
einzugreifen. Außerdem sollte man für den Regelfall und nicht für den
Ausnahmefall optimieren.
function getds(){
$q = "select * from tabelle where fertig=0 and inarbeit=0"
$ds = $db->get($q);
if(!$ds) return false;
$q = "update tabelle set inarbeit = 1 where ";
$q .= "id = ".$ds['id'];
$q .= "and inarbeit = ";
$ret= $db->update($q);
if(!$ret) $ret=getds();
}
Somit habe ich in >99% der Fälle weniger Arbeit (und vor allen Dingen
nicht die ganze Tabelle gesperrt). Nur wenn es wirklich eine Kollision
gibt, dann wird es halt noch mal versucht.
Grüße, Matthias
--
"Hurd will be out in a year"
(Linus Benedict Torvalds, 5. Oktober 1991)
http://groups-beta.google.com/group/comp.os.minix/msg/2194d2 53268b0a1b
Re: Parallele Zugriffe
am 03.03.2005 13:56:07 von Markus Malkusch
Matthias P. Wuerfl:
> Die *ganze*Tabelle*?
Wenn Dir das zu teuer ist, dann benutz' einen anderen Sperrmechanismus (gibt
ja genügende). Aber dann darf's keine Beschwerde geben, wenn an anderer
Stelle Inkonsistenzen auftreten.
> Aber findest Du das nicht ein bisschen unelegant und
> mit-Kanonen-auf-Spatzen-geschossen?
Nein, ist dann wohl Geschmackssache, denn ich persönlich empfinde
nichtdeterministische Algorithmen als Unart.
> Somit habe ich in >99% der Fälle weniger Arbeit
Wer sagt Dir das? Wenn diese Queries so selten sind, stören die kurzen
Tabellensperren nicht. Wenn die Queries aber doch häufiger sind, dann kommt
Dein Algorithmus der (Busy-Waiting) Endlosschleife näher.
--
- Whoisabfrage
Re: Parallele Zugriffe
am 03.03.2005 14:20:09 von Niels Braczek
Matthias P. Wuerfl schrieb:
> function getds(){
> $q = "select * from tabelle where fertig=0 and inarbeit=0"
> $ds = $db->get($q);
> if(!$ds) return false;
> $q = "update tabelle set inarbeit = 1 where ";
> $q .= "id = ".$ds['id'];
> $q .= "and inarbeit = ";
> $ret= $db->update($q);
> if(!$ret) $ret=getds();
> }
Wie stellst du sicher, dass die Funktion jemals abbricht? Wie stellst du
sicher, dass der Stack, der dir für Rekursionen zur Verfügung steht,
nicht überläuft?
MfG
Niels
Re: Parallele Zugriffe
am 03.03.2005 14:28:03 von do.not.REMOVETHAT
Niels Braczek schrieb:
> Wie stellst du sicher, dass die Funktion jemals abbricht?
>> if(!$ds) return false;
> Wie stellst du
> sicher, dass der Stack, der dir für Rekursionen zur Verfügung steht,
> nicht überläuft?
Das kann nur so oft aufgerufen werden wie unbearbeitete DS da sind.
Zudem wird eine weitere Instanz nur aufgerufen, wenn genau zwischen dem
Select und dem Update ein anderes Update war. D.h. jeder andere
Benutzer, der einen Datensatz aufruft kann genau *einen* Funktionsaufruf
erzeugen. Wenn Du es schaffst, so viele Benutzer völlig gleichzeitig
darauf loszulassen, dass diese Rekursion ein Problem wird, dann schmort
Dir vorher eher das Netzwerkkabel durch oder das gleichzeitige Klicken
so vieler Benutzer löst ein Erdbeben aus oder so.
Wenn man davon ausgeht, dass das so 1000 mal laufen kann und es diese
1000 mal in einer Sekunde packt, dann müssten innerhalb einer Sekunde im
Optimalfall (klappt nicht, in Wirklichkeit ein Mehrfaches) 1000 Benutzer
in dieser Sekunde den nächsten Datensatz aufrufen. Wenn *das* passiert
hast Du ein ganz anderes Problem :-)
Grüße, Matthias
--
"Hurd will be out in a year"
(Linus Benedict Torvalds, 5. Oktober 1991)
http://groups-beta.google.com/group/comp.os.minix/msg/2194d2 53268b0a1b
Re: Parallele Zugriffe
am 03.03.2005 14:33:50 von do.not.REMOVETHAT
Markus Malkusch schrieb:
> Wenn Dir das zu teuer ist, dann benutz' einen anderen Sperrmechanismus (gibt
> ja genügende). Aber dann darf's keine Beschwerde geben, wenn an anderer
> Stelle Inkonsistenzen auftreten.
Den anderen Mechanismus habe ich ja vorgeführt und da kommt es auch zu
keiner Inkonsistenz.
> ich persönlich empfinde
> nichtdeterministische Algorithmen als Unart.
Auf flexibe Bedingungen (in den Daten) musst Du flexibel reagieren. Ich
finde das "niemand darf was anderes, jetzt bin ich dran" bei
Multi-User-Systemen unelegant. Das ist ja wie Win95, wo sich jedes
Programm mühelos alles in den Abgrund ziehen konnte.
>>Somit habe ich in >99% der Fälle weniger Arbeit
>
>
> Wer sagt Dir das? Wenn diese Queries so selten sind
Nicht die Queries sind selten, dass haargenau zwischen dem Select und
dem Update ein anderes Update kommt - *das* ist selten.
> Wenn die Queries aber doch häufiger sind, dann kommt
> Dein Algorithmus der (Busy-Waiting) Endlosschleife näher.
Siehe mein anderes Posting: Wenn zwischen *jedem* durchlauf ein anderer
ein Update gemacht hat (also Hunderte oder Tausende Updates pro
Sekunde), dann hast Du ein *ganz* anderes Problem.
Grüße, Matthias
--
"Hurd will be out in a year"
(Linus Benedict Torvalds, 5. Oktober 1991)
http://groups-beta.google.com/group/comp.os.minix/msg/2194d2 53268b0a1b
Re: Parallele Zugriffe
am 03.03.2005 15:20:29 von Niels Braczek
Matthias P. Wuerfl schrieb:
> Niels Braczek schrieb:
>
>> Wie stellst du sicher, dass die Funktion jemals abbricht?
>
> >> if(!$ds) return false;
Damit unterstellst du, dass die Datensätze schneller abgearbeitet werden
als neue hinzukommen. Wer garantiert das?
>> Wie stellst du sicher, dass der Stack, der dir für Rekursionen zur
>> Verfügung steht, nicht überläuft?
>
> Das kann nur so oft aufgerufen werden wie unbearbeitete DS da sind.
Wer garantiert, dass das nicht 2 Milliarden Datensätze sind?
> Zudem wird eine weitere Instanz nur aufgerufen, wenn genau zwischen dem
> Select und dem Update ein anderes Update war. D.h. jeder andere
> Benutzer, der einen Datensatz aufruft kann genau *einen* Funktionsaufruf
> erzeugen. Wenn Du es schaffst, so viele Benutzer völlig gleichzeitig
> darauf loszulassen, dass diese Rekursion ein Problem wird, dann schmort
> Dir vorher eher das Netzwerkkabel durch oder das gleichzeitige Klicken
> so vieler Benutzer löst ein Erdbeben aus oder so.
>
> Wenn man davon ausgeht, dass das so 1000 mal laufen kann und es diese
> 1000 mal in einer Sekunde packt, dann müssten innerhalb einer Sekunde im
> Optimalfall (klappt nicht, in Wirklichkeit ein Mehrfaches) 1000 Benutzer
> in dieser Sekunde den nächsten Datensatz aufrufen. Wenn *das* passiert
> hast Du ein ganz anderes Problem :-)
Das sind Eventualitäten, denen man durch das dafür vorgesehene Locking
ohne Aufwand entgegenwirken kann. Ich verstehe nicht, dass man das nicht
wollen kann.
MfG
Niels
Re: Parallele Zugriffe
am 03.03.2005 22:11:55 von gewinn
Hallo!
> > der Nachteil besteht darin, dass immer nur der letzte zugreifende User
> > speichern darf.
>
> Genau das will der OP verhindern, oder?
Genau.
Ich steig hier noch mal mit ein.
(Vielen Dank für die bisherigen Antworten)
Noch mal einpaar Daten zum Umgebung:
Eine Tabelle mit etwa 30.000 Adressen + Tel.nr.
Diese sollen nacheinander angerufen werden (warum auch immer).
Nun sitzen bis zu 10 Personen an ihren Rechnern und sollen immer eine
Adresse zugewiesen bekommen (nachdem sie die vorherige bearbeitet
haben).
Dafür gibt es zwei Ansätze:
1. Ich lasse durch einen Admin je x Datensätze an die User verteilen
2. Jeder User bekommt die jeweils oberste, noch nicht bearbeitete
Adresse.
-> Dann darf es aber nicht passieren, dass zwei User die gleiche
Adresse anrufen
Re: Parallele Zugriffe
am 04.03.2005 07:59:23 von do.not.REMOVETHAT
Niels Braczek schrieb:
> Damit unterstellst du, dass die Datensätze schneller abgearbeitet werden
> als neue hinzukommen. Wer garantiert das?
Sag' mal, wie artet das Gespräch denn *jetzt* aus?
Nein, Das garantiert natürlich niemand. Aber lass mich noch mal
zusammenfassen:
- Wenn Tausende Zugriffe pro Sekunde Datensätze bearbeiten
- Noch mehr Tausende Datensätze pro Sekunde dazukommen
- plus ein bisschen "Glück"
....dann *könnte* es sein, dass das Script bis zum Tineout versucht einen
Datensatz für die Bearbeitung zu sperren, es aber nicht vor ebendem
Timeout schafft.
> Wer garantiert, dass das nicht 2 Milliarden Datensätze sind?
Niemand.
OK.
Ich gebe zu: Meine Locking-Mechanismen können nicht mehr locken wenn
viele Tausende Schreibzugriffe pro Sekunde sind und/oder Milliarden
Datensätze da sind.
Aber bitte: Zeige mir eine Tabelle mit Milliarden DS, die Du Tausende
male pro Sekunde lockst und ein Update machst. Das will ich sehen.
> Das sind Eventualitäten, denen man durch das dafür vorgesehene Locking
> ohne Aufwand entgegenwirken kann.
Entschuldige, aber bist Du noch ganz knusper? Hast Du gelesen, um was es
dem OP ging? Bist Du Dir nicht darüber im klaren, dass bei der genannten
Applikation das nicht vorkommen *kann*? Hast Du nicht verstanden, dass
"meine Methode" performanter sein *muss* und nur unter Umständen
"Probleme" entstehen können, welche nicht Auftreten *können* (weil kein
Webserver so leistungsfähig ist und weil vorher 1000 andere Dinge nicht
mehr mitmachen).
Genausogut könnte ich versuchen zu überlegen wie sich die Applikation
verhält, wenn die Zeit im Datenbankserver rückwärts läuft.
> Ich verstehe nicht, dass man das nicht wollen kann.
Es gibt 2 Möglichkeiten:
1. Asoziales Locking kompletter Tabellen wegen einem Update was alle
anderen Prozesse blockiert (womit man nie und nimmer Tausende Updates
pro Sekunde hinbekommt)
2. Minimalinvasiver Eingriff ohne andere Prozesse zu blockieren. In dem
Fall eines gleichzeitigen Eingreifens muss es der zweite noch mal versuchen.
Also entweder wir programmieren das jetzt aus und lassen die Programme
gegeneinander antreten oder EOD. Ich habe wirklich besseres zu tun als
hier zu erklären, warum solch ein asoziales Locking doof ist. Ich
bekomme hier "vorgeworfen", dass das bei 1000 parallelen Zugriffen nicht
optimal wäre und bekomme im Gegenzug etwas präsentiert, was unter
dieser Umständen ganz und gar nicht funktionieren würde. Das ist beknackt.
Grüße, Matthias
--
"Hurd will be out in a year"
(Linus Benedict Torvalds, 5. Oktober 1991)
http://groups-beta.google.com/group/comp.os.minix/msg/2194d2 53268b0a1b
Re: Parallele Zugriffe
am 04.03.2005 08:11:03 von do.not.REMOVETHAT
Lars H?hmann schrieb:
> Noch mal einpaar Daten zum Umgebung:
> Eine Tabelle mit etwa 30.000 Adressen + Tel.nr.
> Diese sollen nacheinander angerufen werden (warum auch immer).
> Nun sitzen bis zu 10 Personen an ihren Rechnern und sollen immer eine
> Adresse zugewiesen bekommen (nachdem sie die vorherige bearbeitet
> haben).
> Dafür gibt es zwei Ansätze:
> 1. Ich lasse durch einen Admin je x Datensätze an die User verteilen
> 2. Jeder User bekommt die jeweils oberste, noch nicht bearbeitete
> Adresse.
> -> Dann darf es aber nicht passieren, dass zwei User die gleiche
> Adresse anrufen
OK, Du brauchst ein zusätzliches Feld in Deiner Datenbank. Das nennen
wir mal "bearbeitet". Das ist "boolean" oder smallint oder so. Da steht
für alle DS "0" drin, für "nocht nicht bearbeitet".
Des weiteren brauchst Du ein Feld "in_Bearbeitung_seit", welches ein
datetime-Feld ist. Da steht auch nichts drin - erst mal.
Du schreibst ein Script, welches den nächsten unbearbeiteten DS holt.
Wie das funktioniert ist *hochkomplex*, denn über die Auswirkungen von
Milliarden Datensätzen und Tausenden Updates pro Sekunde auf die gesamte
Applikation ist man sich hier noch nicht im klaren. Vom Prinzip her muss
das aber das machen:
- den nächsten Datensatz, auf den zutrifft:
"bearbeitet" ist "0"
UND
(
"in_Bearbeitung_seit" ist "NULL"
oder
"In_Bearbeitung_set" > ( NOW() + $Zeitspanne )
)
der wir selected
- *gleichzeitig* wird in_Bearbeitung_seit bei dem DS auf now() gesetzt.
- beim speichern wird in_Bearbeitung_seit bei dem DS wieder auf NULL und
"bearbeitet" auf 1 gesetzt.
Grüße, Matthias
--
"Hurd will be out in a year"
(Linus Benedict Torvalds, 5. Oktober 1991)
http://groups-beta.google.com/group/comp.os.minix/msg/2194d2 53268b0a1b
Re: Parallele Zugriffe
am 04.03.2005 13:36:06 von Niels Braczek
Matthias P. Wuerfl schrieb:
> Niels Braczek schrieb:
>
>> Damit unterstellst du, dass die Datensätze schneller abgearbeitet
>> werden als neue hinzukommen. Wer garantiert das?
>
> Sag' mal, wie artet das Gespräch denn *jetzt* aus?
Es wird theoretisch ;-)
> Genausogut könnte ich versuchen zu überlegen wie sich die Applikation
> verhält, wenn die Zeit im Datenbankserver rückwärts läuft.
Naja, da setzt die Physik Grenzen, sodass man sich darum keine Sorgen
machen muss.
> 1. Asoziales Locking kompletter Tabellen wegen einem Update was alle
> anderen Prozesse blockiert (womit man nie und nimmer Tausende Updates
> pro Sekunde hinbekommt)
> 2. Minimalinvasiver Eingriff ohne andere Prozesse zu blockieren. In dem
> Fall eines gleichzeitigen Eingreifens muss es der zweite noch mal
> versuchen.
Nicht anders arbeitet ja auch das Collision Detecting bei Netzwerken. Es
ist also durchaus praktikabel. Im Wesentlichen ging es mir darum klar zu
machen, dass das Verfahren nicht *sicher* ist (im Sinne von: auch
theoretisch kann nichts schief gehen). Bei größeren Operationen
(mehreren Zugriffen) auf die DB hat Locking allerdings nicht
unerhebliche Performanz-Vorteile - zugegebenermaßen für den OP
allerdings nicht relevant.
MfG
Niels