kostenloser Webspace werbefrei: lima-city


Können php Scripts parallel laufen?

lima-cityForumProgrammiersprachenPHP, MySQL & .htaccess

  1. OK, aber ich glaube nicht, dass es sinnvoll ist, mit Crons zu arbeiten, da man dann auf jeden Fall keine direkte Rückmeldung bekommt, die Möglichkeit mit Ajax ist doch viel besser. Oder man verbindet beides und fragt mit Ajax immer wieder ab, ob der eigene Eintrag schon bearbeitet wurde...
  2. Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!

    lima-city: Gratis werbefreier Webspace für deine eigene Homepage

  3. hackyourlife

    Moderator Kostenloser Webspace von hackyourlife

    hackyourlife hat kostenlosen Webspace.

    czibere schrieb:
    du wiederholst dich und ich kann (wiederholt) nur sagen, dass es nicht möglich ist, dass 2 (oder mehr) leute sich gleichzeitig anmelden! (ich weiß es nicht, ob das jetzt endlich rüberkommt).
    Und du verbreitest zum wiederholten Mal Unsinn. Warum?

    czibere schrieb:
    in keinem computer läuft 'gleichzeitig' irgend etwas. alles der reihe nach ;)
    Du hast bestimmt schon etwas von den ganz modernen Computern gehört, wo mehr als ein einziger Prozessorkern vorhanden ist. In diesen Computern kann jeder Prozessor wirklich gleichzeitig einen Arbeitsschritt abarbeiten.

    czibere schrieb:
    das dürfte dein kopfzerbrechen mildern.
    Warum sollte der Scheduler etwas mildern, wenn das doch impliziert, dass Prozesse (fast) jederzeit unterbrochen werden können? Sonst würde dein System wohl immer nur damit beschäftigt sein den "init"-Prozess laufen zu lassen…

    Das Einzige was in einem PHP-Script wirklich atomar abläuft und nicht von einem anderen Prozess gestört werden kann ist ein Datenbankzugriff, da hier das Datenbanksystem "mitdenkt", gleichzeitige Zugriffe abfängt und entsprechend behandelt (z.B. nacheinander ausführt).


    Und jetzt zur Frage: Was ist der Effekt davon, wo kann sowas zu Fehlern führen, …?

    Ich erkläre hier nur die Grundlagen des Problems…

    Man stelle sich folgenden Code vor:
    $id = getNextFreeID(); // nächste freie ID aus der Datenbank ermitteln
    // $info = …; Informationen zusammenbauen
    registerUser($id, $info); // User mit ID und info in die Datenbank eintragen
    Dieser Code wird nun 1x ausgeführt. Dabei wird er wie erwartet funktionieren.

    Wenn dieser Code aber mehrmals parallel ausgeführt wird kann es schon zu fehlern kommen (ob das jetzt auf mehreren Prozessoren tatsächlich gleichzeitig oder per Scheduler unterbrochen und hintereinander stattfindet ist dabei egal).

    Man stelle sich dazu folgendes vor: das Script läuft 2x parallel. Das 1. Script wird ausgeführt und hat von getNextID() eine ID bekommen. Das 2. Script ruft ebenfalls diese Funktion auf und bekommt die Gleiche ID. Beide Scripte füllen $info und tragen den User mit registerUser in die Datenbank ein. Das Problem ist jetzt, dass beide die gleiche ID bekommen haben, da zum Zeitpunkt wo die ID gelesen wurde sie ja noch gültig war.

    Damit das nicht vorkommen kann müsste der Block (der normalerweise auch als "Critical Section" bezeichnet wird) von getNextFreeID() bis registerUser() 1. atomar, also unteilbar, ablaufen, darf also vom Scheduler nicht unterbrochen werden können und 2. damit es auf echten SMP-Systemen keine Probleme gibt müsste per Lock sichergestellt werden, dass sich immer nur ein einziger Thread in diesem Bereich aufhalten kann. Das Lock würde übrigens gleichzeitig auch für Punkt 1 sorgen.

    Was aber auch klar ist: je länger eine "critical Section" ist, desto mehr andere Threads müssen warten, bis sie wieder frei ist → Performance.

    Soviel zum Ausflug in die Welt der Nebenläufigkeit.

    Hoffentlich wurde damit auch voloyas (indirekte) Frage beantwortet.

    Beitrag zuletzt geändert: 13.11.2012 19:46:19 von hackyourlife
  4. Autor dieses Themas

    unlikus

    unlikus hat kostenlosen Webspace.

    und was soll ich jetzt machen, die critsche Phase dauert entweder etwa 0,5 Secounden oder alle 12 Registrationen bis zu 2 Sekunden.
    gibt es denn keine Möglcihkeit php zu sagen: Führe dieses Script immer nur 1x aus.
  5. Du kannst das Ganze doch einfach anders rum machen, denke ich. Erst mit MySQL auto-increment einen neuen Datenbankeintrag erstellen und dann abfragen, welcher erzeugt wurde. Müsste klappen, oder hat jemand Einsprüche?
  6. 1. IDs per Autoinkrement befüllen lassen und nicht über getID rausziehen. das DBMS ist schon groß und kann das ganz alleine...

    2. über Ajax eine Sperrtabelle befüllen, die du angelegt hast:
    -alle leute, die sich grad im registrierungsformular befinden füllen es nacheinander aus
    -teilweise ist bekannt, welche Daten bei einem post erwartet werden
    -in Echtzeit kann mitgeteilt werden, ob gerade ein anderer anmelder denselben Benutzernamen etc in Arbeit hat


    3.bau dir ene Transaktionstabelle
    -eingehende SQL-Inserts/Updates werden aufgefangen, jeder weiterer Aufruf forciert die Ausführung eines weiteren. vermerke die Session ID und liefere einen Wahrheitswert zurück (erfolgreich/nicht erfolgreich)
    -abfangen multipler Posts ohne weiteres möglich
    -sperrkriterien können einfach implementiert werden
    -dann lässt du einfach einen worker drüber laufen, der nur aus der transaktionstabelle in die Datentabelle füttert...



    1 ist pflicht eigentlich


    zwischen 2 und 3 kannst du auswählen, was du machst...




    tobiworlds schrieb:
    Du kannst das Ganze doch einfach anders rum machen, denke ich. Erst mit MySQL auto-increment einen neuen Datenbankeintrag erstellen und dann abfragen, welcher erzeugt wurde. Müsste klappen, oder hat jemand Einsprüche?


    reicht nicht für alle Fälle... meine Methode nummer 3 ist totsicher, aber auch die aufwändigste, langsamste und rechenintensivste...

    methode 2 ist fast gleich, aber die sperrtabelle wird dann durch den post geleert. es entsteht eine menge traffic



    und wer langeweile hat und sowieso keine besucher, kann 2 und 3 kombinieren...
  7. Autor dieses Themas

    unlikus

    unlikus hat kostenlosen Webspace.

    1. mache ich soweiso und ajax finde ich zu gefährlich wenn jemand kein Javascript aktiviert hat.
    Mehtode 3 ist wie du gesagt hast sehr aufwändig, vielleicht hat ja jemand noch eine bessere Idee
  8. unlikus schrieb:
    1. mache ich soweiso und ajax finde ich zu gefährlich wenn jemand kein Javascript aktiviert hat.
    Mehtode 3 ist wie du gesagt hast sehr aufwändig, vielleicht hat ja jemand noch eine bessere Idee


    Wie wäre es, wenn du einfach eine Abfrage generierst, diese in eine temporäre Datei oder Variable schiebst und alle X- Sekunden mittels nem Cronjob ablaufen lässt? Bei einer Datei beispielsweise könntest du somit jede Zeile einzeln auslesen, damit ist das "nacheinander" garantiert... Bei einer Variable beispielsweise einem Array, kannst du ja auch die Einträge nacheinander ablaufen lassen...

    Damit hätte zwar ab und zu ein User eine Latenz, diese hält sich aber recht gering, da du ja prüfen kannst welche User gerade online sind und dementsprechend die Zeit festlegen. Beispielsweise sind 5 User online, dein Script wird alle 5 Sekunden ausgeführt, bzw. die Variable abarbeitet, wenn 10 online sind, dann alle 2,5 Sekunden oder so ähnlich..

    War nur so ne Idee, nachdem ich hier grad mal durchgelesen habe...


    PS: Ich würde dann lieber eine Variable nehmen, Datei wäre zu unsicher...
  9. kill-a-teddy schrieb:

    Wie wäre es, wenn du einfach eine Abfrage generierst, diese in eine temporäre Datei oder Variable schiebst und alle X- Sekunden mittels nem Cronjob ablaufen lässt? Bei einer Datei beispielsweise könntest du somit jede Zeile einzeln auslesen, damit ist das "nacheinander" garantiert... Bei einer Variable beispielsweise einem Array, kannst du ja auch die Einträge nacheinander ablaufen lassen...

    Damit hätte zwar ab und zu ein User eine Latenz, diese hält sich aber recht gering, da du ja prüfen kannst welche User gerade online sind und dementsprechend die Zeit festlegen. Beispielsweise sind 5 User online, dein Script wird alle 5 Sekunden ausgeführt, bzw. die Variable abarbeitet, wenn 10 online sind, dann alle 2,5 Sekunden oder so ähnlich..

    War nur so ne Idee, nachdem ich hier grad mal durchgelesen habe...


    PS: Ich würde dann lieber eine Variable nehmen, Datei wäre zu unsicher...



    Damit wären wir wieder bei meiner Methode 3... nur dass du es in eine Datei packen willst... im Endeffekt gibt es keine weiterne möglichkeiten... entweder der TE kann sich einen Transaktionsmanager scripten mit Puffertabelle oder er lässt die Finger ganz davon...

    cron wäre die variante die ich über Ajax einbinden wollte, weil Cron kann ausfallen... wenn ajax ausfällt, ist der user selbst schuld aber ein anderer User würde dann die ausführung garantieren können...


    und irgendwo geht es mir auf den Sack... die TEs fragen nach allgemeiner Hilfe, wir geben anregungen und dann fragen die weiter und geben erst ruhe, bis denen einer eine fertige lösung scriptet... ich hab bereits alles gesagt was dazu zu sagen ist und damit klinke ich mich aus der Diskussion in diesem Thread aus...

    Beitrag zuletzt geändert: 14.11.2012 10:59:05 von sebulon
  10. Autor dieses Themas

    unlikus

    unlikus hat kostenlosen Webspace.

    Hab jetzt eine Lösung für mein Problem:
    Ich habe eine mysql zelle.
    Wenn das Script startet wird der Inhalt dieser Zelle abgefragt, wenn dieser 1 ist, wird später noch einmal nachgefragt, wenn dieser 0 ist wird der wert um inkremiert und nach 100ms wird erneut der Wert abgefragt, wenn dieser 1 ist wird das Script abgefragt, wenn dieser größer als 1 ist wird die zelle auf 0 gesetzt und es wird in einer zufälligen Zeit das ganze nocheinmal versucht.

    Hoffe das funktioniert
  11. burgi

    Co-Admin Kostenloser Webspace von burgi

    burgi hat kostenlosen Webspace.

    unlikus schrieb:
    Hab jetzt eine Lösung für mein Problem:
    Ich habe eine mysql zelle.
    Wenn das Script startet wird der Inhalt dieser Zelle abgefragt, wenn dieser 1 ist, wird später noch einmal nachgefragt, wenn dieser 0 ist wird der wert um inkremiert und nach 100ms wird erneut der Wert abgefragt, wenn dieser 1 ist wird das Script abgefragt, wenn dieser größer als 1 ist wird die zelle auf 0 gesetzt und es wird in einer zufälligen Zeit das ganze nocheinmal versucht.

    Hoffe das funktioniert

    Und wie willst du verhindern, dass 2 aufgerufene Skripte zur gleichen Zeit den Wert abfragen, und beim Setzen auf die 1 in Kollision geraten?
    Zelle ist 0
    Skript 1 fragt nach, bekommt 0
    Skript 2 fragt nach, bekommt 0
    Skript 1 setzt die Zelle auf 1, und beginnt, den User anzulegen
    Skript 2 hat ja auch 0 bekommen, setzt also die Zelle erneut auf 1, und beginnt ebenfalls, die Arbeit zu verrichten
    Ich denke, das ist wiederum die Situation, die du verhindern wolltest...
    Inwieweit dir das Verhalten, das hackyoulife schilder
    Das Einzige was in einem PHP-Script wirklich atomar abläuft und nicht von einem anderen Prozess gestört werden kann ist ein Datenbankzugriff, da hier das Datenbanksystem "mitdenkt", gleichzeitige Zugriffe abfängt und entsprechend behandelt (z.B. nacheinander ausführt).

    Das Leben wirklich einfacher macht, kann ich nicht beurteilen.

    Sicher wäre in jeden Fall, eine Queue zu erzeugen:
    Skript 1 fügt einen Eintrag hinzu, dass es einen User anlegen will
    Skript 2 fügt einen Eintrag hinzu, dass es einen User anlegen will
    ein drittes Skript checkt, ob die Warteschlange leer ist
    nein, ist sie nicht
    -> Zeile 1 wird geholt, User 1 wird angelegt
    Zeile aus der Schlange wird entfernt
    checkt, ob Schlange leer
    nein, noch immer nicht
    nächsten Befehl holen, ausführen.
    Wenn die Warteschlange als MySQL-Tabelle angelegt ist, mit einer fortlaufenden ID (also als AutoIncrement), dann kannst du Kollisionen wirkungsvoll verhinern. Der Aufwand hält sich meiner Meinung nach in Grenzen.
    So kannst du gleich Userlöschungen etc. auch miterledigen, wenn du verschiedene "Event-IDs" verwendest, 1 legt einen User an, 2 löscht einen, ...
  12. unlikus schrieb:
    Hab jetzt eine Lösung für mein Problem:
    Ich habe eine mysql zelle.
    Wenn das Script startet wird der Inhalt dieser Zelle abgefragt, wenn dieser 1 ist, wird später noch einmal nachgefragt, wenn dieser 0 ist wird der wert um inkremiert und nach 100ms wird erneut der Wert abgefragt, wenn dieser 1 ist wird das Script abgefragt, wenn dieser größer als 1 ist wird die zelle auf 0 gesetzt und es wird in einer zufälligen Zeit das ganze nocheinmal versucht.

    Hoffe das funktioniert


    Klingt aber arg Serverlastig ^^ Gutes Gelingen, nur wird dir das nicht weiter helfen :D Da immer noch zwei Benutzer sich gleichzeitig registrieren können ^^ Wenn einer in der Warteschlange ist und der andere zufällig genau nach 100ms klickt ^^
  13. Autor dieses Themas

    unlikus

    unlikus hat kostenlosen Webspace.

    nein, nach genau 100ms ist die mysql Zelle ja 1 und das zweite script wird erst ausgeführt wenn das laufende script die Zelle wieder auf 0 setzt. Und so Serverlastig ist die ganze Sache auch nicht, nur wenn der unwahrscheinliche Fall eintritt, dass sich 2 User gleichzeitig registrieren

    Beitrag zuletzt geändert: 14.11.2012 17:30:14 von unlikus
  14. Aber das zu verhindern, war doch der einzige Sinn des Ganzen, wenn ich noch nicht abgedriftet bin!?
  15. Jetzt bin ich total verwirrt? Ich denke der ganze Thread dreht sich um den Fall, dass sich zwei Benutzer gleichzeitig anmelden? Oo
  16. Also ich finde, das klingt stark 'komisch' bzw. kann ich jetzt aus dieser Mthode garnicht herauslesen wo genau der Sinn ist zumal es so aussieht, als ob das, wie kill-a-teddy bereits sagte, nicht für die beste Performance sorgt.

    Vielleicht habe ich es überlesen, aber beantworte doch bitte einmal diese Frage:
    Warum geht kein Ai in der Datenbank?

    MFG


    EDIT
    wegen Platzhaltern (falls das der Grund ist, den du mal erwähnt hast)

    Wieso schreibst du die Platzhalter in die DB?
    Leg sie doch als Defaultwert in die Abfrage.

    Beispiel: (einfach gehalten!)

    in der DB stehen 30 Einträge.
    in der Welt gibt es aber 50 Plätze -> 20 Platzhalter

    Die Abfrage wäre dan so:
    $query = "SELECT ...";
    $resul = mysql_query($query);
    $i = 0;
    while($row = mysql_fetch_object($result)){
      $i++
      echo "Eintrag nr: ".$1;
    //Weitere Verarbeitung der Daten
    }
    
    for($j = $i;$j<50;$j++){
      echo "Platzhalter nr:".$j;
    }


    Beitrag zuletzt geändert: 14.11.2012 23:52:38 von programtools
  17. hackyourlife schrieb:
    Und du verbreitest zum wiederholten Mal Unsinn. Warum?
    genau darum ;)

    also ich fasse das mal kurz zusammen, und ihr werdet das (hoffentlich) alle auf der zunge zergehen lassen:
    PHP does not support creating threads.
    daher können threads (mehrzahl!) auch nicht in unterschiedlichen kernen (wieder mehrzahl!) laufen.

    noch immer fragen über diesen künstlich aufgeblasenen schwachsinn hier ...?

    ==== edit ====
    OH JA! und für @unlikus: wenn du das problem wirklich haben willst, probiere mal das aus (man kann ja sein eigenes leben mit allen mitteln versauen ;)

    Beitrag zuletzt geändert: 15.11.2012 5:50:03 von czibere
  18. burgi

    Co-Admin Kostenloser Webspace von burgi

    burgi hat kostenlosen Webspace.

    czibere schrieb:
    PHP does not support creating threads.

    Das streitet ja doch auch gar niemand ab!
    Du vergisst aber, dass normalerweise (so kenne ich das zumindest) für jeden Aufruf / User eine Apache-Instanz die Seiten ausliefert, sprich: 2 User, 2 Apachen, jede Instanz bedient sich PHP. 2 Instanzen -> 2 Kerne. Das ist auch der Fall, den hackyourlife beschreibt, und der weiß in solchen Sachen für gewöhnlich, wovon er schreibt. Das hat so also auch nichts mit Threadprogrammierung zu tun ...
  19. Autor dieses Themas

    unlikus

    unlikus hat kostenlosen Webspace.

    Also mein reg script ist nicht so einfach, dass bei gleichzeitiger ausführung nur probleme mit platzhaltern entstehen würden.
    Und meine Möglcihkeit zu verhindern, dass 2 den gleichen Code ausführen funktioniert doch?
    Erst wird geprüft wird schon ein Script registriert, dass dauert insgesammt 100ms, also doch kein Performance verlust, nur wenn der unwahrscheiliche Fall eintritt, dass sich wirklich 2 Nutzer innerhalb 100ms anmelden dauert das Script eventuell ein paar Sekunden mehr, aber es macht keine probleme. Wenn jemand also einen Denkfehler findet wäre nett ihn mir auch konkret mitzuteilen und nicht einfach nur was über den ganzen Algorythmus zu sagen
  20. Wie wäre es, wenn Du Dein Script mal postest? So sieht es immer noch so aus, als wäre Dein Problem genauso wenig gelöst wie am Anfang.
  21. Autor dieses Themas

    unlikus

    unlikus hat kostenlosen Webspace.

    hab bis jetzt meine Methode noch nicht geproggt. hier aber mal das meomentne regscript:

    $code=rand(100000,999999);
    
            mysql_query("INSERT INTO user (name, passwort, team_name, email, code, geld, reg) VALUES ('".$name."', '".$pass."', '".$team."', '".$email."', '".$code."', '100000', '".time()."')");
            $temp=mysql_fetch_row(mysql_query("SELECT id FROM user WHERE name='".$name."'"));
            $id=$temp[0];
            mysql_query("INSERT INTO user_stadion (id, name, stehp, sitzp, gsitzp, vipp) VALUES ('".$id."', 'Stadion Name', '5', '9', '18', '25')");
    
            $temp=mysql_fetch_row(mysql_query("SELECT ligen FROM main WHERE 1"));
            $ligen=$temp[0];
            $temp=mysql_fetch_row(mysql_query("SELECT id, sieg, niederlage, unentschieden, torein, toraus, platz FROM user_liga WHERE ml='1' AND ligaid='".$ligen."' LIMIT 1"));
            $managerlos=$temp[0];
            mysql_query("INSERT INTO user_liga (id, ligaid, sieg, niederlage, unentschieden, torein, toraus, platz) VALUES ('".$id."', '".$ligen."', '".$temp[1]."', '".$temp[2]."', '".$temp[3]."', '".$temp[4]."', '".$temp[5]."', '".$temp[6]."')");
            mysql_query("UPDATE user_liga SET ligaid='".($ligen+1)."', sieg='0', niederlage='0', unentschieden='0', torein='0', toraus='0', platz='0' WHERE id='".$temp[0]."'");
    
            $anzahl=mysql_result(mysql_query("SELECT COUNT(id) FROM user_liga WHERE ligaid='".($ligen+1)."' "),0);
            if($anzahl==12)
            {
                mysql_query("UPDATE main SET ligen=ligen+'1' WHERE 1");
                include("geheim/spielplan_reg.php");
            }
  22. Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!

    lima-city: Gratis werbefreier Webspace für deine eigene Homepage

Dir gefällt dieses Thema?

Über lima-city

Login zum Webhosting ohne Werbung!