Doppelte MySQL-Einträge

  • Hallo,

    ich bin vor ein paar Tage mit meinem Browsergame an den Start gegangen und bisher wird es ordentlich geklickt. Jetzt hab ich das Problem das anscheinend einige Datenbankeinträge doppelt gemacht werden und ich hab keine Ahnung woran das liegt...

    Naja, da ich so ein Problem noch nie hatte weiß ich nicht was ich dagegen tun könnte. Vielleicht hat ja jemand von euch ein Vorschlag hierzu?

    MfG
    Red


  • Deine Infos reichen nicht. Was wird wann doppelt eingetragen? Wie sieht die DB-Struktur bzw. die entsprechende Tabelle aus? Wie sieht das dazugehörige Script aus?

  • Naja, es handelt sich um ein Weltraum-Strategiespiel. Dabei können die Spieler Flotten auf andere Planetzen schicken etc. daher musste ich für die Ausführung der Missionen am Zielplaneten bzw. bei der Rückkehr ein Eventhandler schreiben.
    Das Problem kommt nun bei der Rückkehr der Schiffe vor, in dem Moment in der die Schiffe aus der "flotten" (Tabelle der derzeit fliegenden Flotten) in die "planeten" (Tabelle aller Planeten und dessen Werte wie Gebäude, Schiffe) übertragen werden. Bei diesem Vorgang wird der Eintrag ab-und-zu doppelt in die "planeten"-Tabelle eingetragen. Wie erwähnt geschieht des mehr oder weniger zufällig, daher denke ich, es liegt daran, dass mehrere Spieler diesen Eventhandler (der in jede Datei includiert & ausgeführt wird) aufrufen und somit eben die Befehle zeitgleich ausgeführt und daher verdoppelt werden.

    Ich hab es mal mit LOCK TABLES versucht, weil ich dachte die Funktion sei für solche Probleme, jedoch scheint es trotzdem noch vorzukommen.

    PHP
    $db->query("LOCK TABLE 'mehrere Tabellen' WRITE", "");
    $EVENTHANDLER= new eventhandler;
    if ($EVENTHANDLER->initialisieren()) {
        $EVENTHANDLER->startevents();
    }
    $db->query("UNLOCK TABLES",'');

    Der Datenbank-Benutzer besitzt das Recht, LOCK TABLES auszuführen.

    Ich hoffe diese Infos reichen um einen kleinen Überblick zu bekommen?

    MfG


  • Was willst du denn mit dem LOCK erreichen? Dass der andere garnicht ausgeführt wird, oder?
    Schick mal den ganzen Query, die bloßen DB-Namen sind ja wohl kaum geheim.

    Probier eventuell mal die shm- und sem-Funktionen.

    Edit:
    Ich habe jetzt noch einmal nachgeschaut:
    LOCK TABLE wirkt quasi wie ein Semaphore: Das Script, das zu spät kommt, muss warten, bis das andere fertig ist, die Aktion wird dennoch durchgeführt.
    Ich schreib mal was kleines:


    Alternativ kannst du aus $c (connection) und $s (semaphore) auch statische Klassenmember machen oder das Ganze nicht statisch aufziehen. So kannst dus dann anwenden, du brauchst eben ne Transaction-ID:


    Die Daten werden hierbei nur erzeugt, wenn nicht gelockt wurde. Wenn die Daten in jedem Thread einzeln erzeugt werden sollen, sieht es so aus:


    Hierbei muss nicht mehr zwingend eine Funktion zur Datensatzerzeugung erstellt werden, dafür macht jeder Thread sein eigenes Ding.

    Hinweise:
    Das ganze funktioniert nicht unter Windoof.
    $transactionid muss ein Integer sein.
    $data kann eine beliebige Variable sein. (Objekt, Array,..., bloß keine Ressource oder boolesches false)

    Viele liebe Grüße
    The User

    Edit:
    Ich habe es jetzt getestet und es geht.
    Wer es probieren möchte, öffnet einfach 2-3mal dieses Script:


    Und - oh Wunder - einer lockt und die anderen erhalten die selbe Zufallszahl.