Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Gleichzeitige Transaktionen in einer Webanwendung verhindern

Ich bin froh, dass Sie erkennen, dass dies nur eine schlechte und vorübergehende Lösung ist und Sie Ihren Code optimieren sollten. Vergessen Sie Ihre Token und so. Der einfachste und dennoch effiziente Weg ist wahrscheinlich, eine exklusive Dateisperre für eine freigegebene Datei pro Vorgang zu haben. Das kann man sich vorstellen wie ein Stück Holz und nur einer kann es halten und nur wer es hält darf reden oder etwas tun.

<?php
    $fp = fopen("/tmp/only-one-bed-available.txt", "w+");

    if (flock($fp, LOCK_EX)) { // do an exclusive lock

         // do some very important critical stuff here which must not be interrupted:
         // sleeping.
         sleep(60);
         echo "I now slept 60 seconds";
        flock($fp, LOCK_UN); // release the lock
    } else {
        echo "Couldn't get the lock!";
    }

    fclose($fp);
?>

Wenn Sie dieses Skript 10 Mal parallel ausführen, dauert es 10 Minuten, bis es fertig ist (weil nur ein Bett verfügbar ist!) und Sie sehen alle 60 Sekunden (ungefähr) das Echo "Ich habe jetzt geschlafen ...".

Dies serialisiert ALLE Ausführungen dieses Codes GLOBAL. Das ist wahrscheinlich nicht das, was Sie wollen (Sie wollen es pro Benutzer, nicht wahr?) Ich bin sicher, Sie haben so etwas wie Benutzer-IDs, ansonsten verwenden Sie die fremde IP-Adresse , und haben einen eindeutigen Dateinamen für jeden Benutzer:

<?php $fp = fopen("/tmp/lock-".$_SERVER["REMOTE_ADDR"].".txt", "w+"); ?>

Sie können auch einen Sperrdateinamen für eine Gruppe von Operationen definieren. Vielleicht kann der Benutzer einige Sachen parallel machen, aber nur diese Operation macht Probleme? Geben Sie ihm ein Tag und fügen Sie es in den Dateinamen der Sperre ein!

Diese Praxis ist wirklich nicht so schlimm und kann verwendet werden! Es gibt nur wenige Möglichkeiten, es schneller zu machen (Mysql-Interna, gemeinsam genutzte Speichersegmente, Serialisierung auf einer höheren Ebene wie Load Balancer ...)

Mit der oben geposteten Lösung können Sie dies in Ihrer Anwendung tun, was wahrscheinlich gut ist. Sie können dasselbe Schema auch in Mysql verwenden:http://dev.mysql.com/doc/refman/5.0/en/miscellaneous-functions.html#function_get-lock

Aber die PHP-Implementierung ist wahrscheinlich einfacher und besser für Ihren Anwendungsfall.

Wenn Sie wirklich eine noch elegantere Lösung finden möchten, sehen Sie sich einfach diese Funktion an http://www.php.net/manual/en/function.sem-get.php