Mysql
 sql >> Base de données >  >> RDS >> Mysql

Empêcher les transactions simultanées dans une application Web

Je suis heureux que vous réalisiez que ce n'est qu'une mauvaise solution temporaire et que vous devriez optimiser votre code. Oubliez vos jetons et autres. Le moyen le plus simple et toujours efficace est probablement d'avoir un verrou de fichier exclusif sur un fichier partagé par opération. Vous pouvez imaginer cela comme un morceau de bois et un seul peut détenir une pièce d'identité et seul celui qui la détient est autorisé à parler ou à faire quelque chose.

<?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);
?>

Si vous exécutez ce script 10 fois en parallèle, cela prendra 10 minutes pour finir (car il n'y a qu'un seul lit de disponible !) et vous verrez l'écho "I now sleepy..." toutes les 60 secondes (environ).

Cela sérialise TOUTES les exécutions de ce code GLOBALEMENT. Ce n'est probablement pas ce que vous voulez (vous le voulez par utilisateur, n'est-ce pas ?) Je suis sûr que vous avez quelque chose comme les ID utilisateur, sinon utilisez l'adresse IP étrangère , et avoir un nom de fichier unique pour chaque utilisateur :

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

Vous pouvez également définir un nom de fichier de verrouillage pour un groupe d'opérations. Peut-être que l'utilisateur peut faire des trucs en parallèle mais seule cette opération pose problème ? Donnez-lui une balise et incluez-la dans le nom du fichier de verrouillage !

Cette pratique n'est vraiment pas si mal et peut être utilisée ! Il n'y a que peu de moyens de le faire plus rapidement (éléments internes mysql, segments de mémoire partagée, sérialisation sur une couche supérieure comme l'équilibreur de charge...)

Avec la solution publiée ci-dessus, vous pouvez le faire dans votre application, ce qui est probablement bon. Vous pouvez également utiliser le même schéma dans Mysql :http://dev.mysql.com/doc/refman/5.0/en/miscellaneous-functions.html#function_get-lock

Mais l'implémentation de PHP est probablement plus facile et meilleure pour votre cas d'utilisation.

Si vous voulez vraiment botter le cul, une solution encore plus élégante, il suffit de consulter cette fonction http://www.php.net/manual/en/function.sem-get.php