sql >> Base de Datos >  >> RDS >> Mysql

Impedir transacciones simultáneas en una aplicación web

Me alegro de que se dé cuenta de que es solo una solución mala y temporal y que debe optimizar su código. Olvídese de sus tokens y demás. La forma más fácil y aún eficiente es probablemente tener un bloqueo de archivo exclusivo en un archivo compartido por operación. Puedes imaginar esto como un trozo de madera y solo uno puede tener una identificación y solo quien la tiene puede hablar o hacer algo.

<?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 ejecuta este script 10 veces en paralelo, tardará 10 minutos en terminar (¡porque solo hay una cama disponible!) y verá el eco "Ahora dormí..." cada 60 segundos (aproximadamente).

Esto serializa TODAS las ejecuciones de este código GLOBALMENTE. Esto probablemente no es lo que desea (lo desea por usuario, ¿no es así?) Estoy seguro de que tiene algo así como ID de usuario; de lo contrario, use la dirección IP extranjera y tener un nombre de archivo único para cada usuario:

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

También puede definir un nombre de archivo de bloqueo para un grupo de operaciones. ¿Quizás el usuario puede hacer algunas cosas en paralelo, pero solo esta operación genera problemas? ¡Dale una etiqueta e inclúyela en el nombre del archivo de bloqueo!

¡Esta práctica realmente no es tan mala y puede usarse! Solo hay pequeñas formas de hacerlo más rápido (internos de mysql, segmentos de memoria compartida, serialización en una capa superior como el balanceador de carga...)

Con la solución publicada anteriormente, puede hacerlo en su aplicación, lo que probablemente sea bueno. También puede usar el mismo esquema en Mysql:http://dev.mysql.com/doc/refman/5.0/en/funciones-varias.html#function_get-lock

Pero la implementación de PHP es probablemente más fácil y mejor para su caso de uso.

Si realmente quieres patear traseros, hay una solución aún más elegante, solo revisa esta función http://www.php.net/manual/en/function.sem-get.php