PHP Scripts und Konsistenz beim gleichzeitigen Abrufen

player1

Mitglied
Hallo,
ich mache mir gerade Gedanken über mögliche Probleme in PHP Applikationen.
Wenn Scripts von zig Leuten zur gleichen Zeit abgerufen werden und hierbei Daten in zB in der Datenbank geändert, gelöscht und abgerufen werden, ist es doch grundsätzlich möglich, dass Inkonsistenzen in der Datenbank entstehen. Durch das gleichzeitige Aufrufen eines Scripts könnte ja zB versehentlich Daten abgerufen werden die eventuell nicht mehr bestehen, da Milisekunden vorher die jeweiligen Datensätze gelöscht wurden durch ein fast zeitgleichen Abruf.

Ich kenne diese Probleme vorallem in anderen Sprachen wie Java, die Theads unterstützen. Hier ist es ein selbstverständliches Problem und es gibt verschiedene Techniken um zB die Deadlocks usw zu verhinden.

Ich würde gerne wissen, wie PHP intern läuft. Sind die Abrufe eigentlich parallel oder werden sie hintereinander abgerufen. Wäre dies der Fall, dann wären meine Gedanken hierüber jedenfalls hinfällig :D
Ansonsten würde ich gerne mehr darüber erfahren, wie ihr die Probleme löst und ob es gute Seiten gibt, die sich mit guten (und möglichst perfomanten) Lösungen beschäftigen.

Viele Grüße
Johannes
 
PHP kennt zunächst einmal keine Threads. Aber der aufrufende Prozess (i.d.R. der Webserver Apache) kennt jene. Daher können auch mehrere PHP-Sessions gleichzeitig laufen. Auch die Zugriffe können quasi-gleichzeitig laufen. Quasi daher, weil das auch von der Anzahl der Prozessor-Kerne abhängt. Ebenso auch vom OS-Scheduler.

So kann es durchaus vorkommen, das ein User einen Datensatz ändert, während ein ander ihn ebenfalls ändern will. Das führt bei unsachgemäßer Programmierung dann tatsächlich zu Inkonsistenzen.

Das kannst du als Entwickler aber abfangen, in dem du bspw. Datenbank-Tabellen/Rows oder Columns lockst. Wie das geht kannst du in der Dokumentation des jeweiligen Datenbank-Systems erfahren. Bei MySQL findest du es z.B. hier: http://dev.mysql.com/doc/refman/5.1/de/lock-tables.html
 
Danke für deine schnelle Antwort. Ich glaube, die Lösung mit den LockTables erspart mir schonmal Kummer und Sorgen in Zukunft ;)
Aber in jedem Fall werden Requests nicht mehr so schnell verarbeitet werden können durch den Lock von Tables, da andere "Threads" ja warten müssen, bis es wieder freigegeben wird. Die Performance ist in jedem Fall ja langsamer.
Aber dies ist wohl ein notwendiges Übel wenn alles stabil laufen soll.
Gibt es ansonsten noch andere clevere phpspezifische Lösungen für dieses Problem?
 
Ja, ein Problem kann man recht gut lösen. Das Problem Nr. 1 lässt sich folgendermaßen umgehen:

User A selected einen Datensatz und stellt das Ergebnis auf einer Seite in einem beschreibbaren dar, inkl. eines Submit-Buttons zum Ändern des Wertes.

User B updated den Wert ohne ihn vorher zu auszulesen.

User A ändert den Wert im Text-Feld und drückt den Submit-Button. Normalerweise würde die Datensatzänderung von B nun einfach überschrieben. Wenn User A aber, während er ihn ausgelesen und dargestellt hat, sich auch gleichzeitig den Wert merkt (Session/Hidden Form Element/etc), kann bevor der Wert erneut einfach geändert wird, zunächst eine Prüfung statt finden, ob der originale Wert eigentlich noch drin steht.

Klingt jetzt etwas kompliziert, aber so wird man es machen müssen, an Stellen, wo sowas vorkommen kann. Bspw. in einem Shop, an dem mehrere Leute gleichzeitig administrieren, sprich Preise ändern, Rabatte anpassen, etc.
 
"Klingt jetzt etwas kompliziert, aber so wird man es machen müssen, an Stellen, wo sowas vorkommen kann. Bspw. in einem Shop, an dem mehrere Leute gleichzeitig administrieren, sprich Preise ändern, Rabatte anpassen, etc."

Könnte man nicht zum Beispiel den Rows in der Datenbank einen Flag "locked" mitgeben für die Zeit, die ein Shopverwalter A zB Rabatte bearbeitet? So würde eine zweite Person B, die auf die Daten zugreifen will direkt eine Fehlermeldung bekommen.
Ich könnte mir zB vorstellen, das man dieses Problem mithilfe einer Datenbankklasse generell lösen könnte ohne individuell auf jedes Problem zu reagieren.

PHP:
$lockme=true; //Datensätze sperren
$dbobj->query("select * from rabatte", $lockme, $userA_DerRabatteAendernWill); //objekt dient nur der anschauung

Nach einem weiteren Request würde der Lock in jedem Fall wieder aufgehoben werden. Will man für User A den Lock erhalten lassen, muss man ihn frühzeitig erneuern, sonst geht er verloren.
Klar, bricht der User A einfach ab, stellt den Computer aus und geht nach Hause, dann würde der Lock bestehen bleiben. Hier würde evtl ein Zeitlimit noch zusätzlich was nützen.

Ein User B, der auf jene Datensätze zugreifen würde könnte eine standardisierte Fehlermeldung bekommen, zB "Ein anderer Benutzer editiert gerade Daten"..

So könnte man diesesProblem doch theoretisch auch lösen oder nicht?
 
Der Ansatz ist auch gut! Vor allem etwas generischer, da ein Locking in der DB immer abstrakt ist. Egal welche Sprache, man muss den gleichen Mechanismus ausimplementieren.

Problematisch daran ist, das man die DB-Schnittstelle erstmal generisch bauen muss. Sprich man müsste ein Framework ähnlich Zend_DB bauen, weil man sonst für jeden SQL-Query den Check hinten anhängen müsste.

Aber Zend_Db könnte man relativ einfach auf ein solches Vorgehen erweitern. Ich bin mir sicher, das es auch andere Frameworks gibt, die eine solche Extension als Klassen-Abstraktion anbieten.
 
Zurück