Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Impedir transações simultâneas em um aplicativo da web


Fico feliz que você perceba que é apenas uma solução ruim e temporária e você deve otimizar seu código. Esqueça seus tokens e outras coisas. A maneira mais fácil e ainda eficiente é provavelmente ter um bloqueio de arquivo exclusivo em um arquivo compartilhado por operação. Você pode imaginar isso como um pedaço de madeira e apenas um pode segurar o id e só quem o segura pode falar ou fazer alguma coisa.
<?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);
?>

Se você executar este script 10 vezes paralelamente, levará 10 minutos para terminar (porque há apenas uma cama disponível!) e você verá o eco "agora dormi..." a cada 60 segundos (aproximadamente).

Isso serializa TODAS as execuções deste código GLOBALMENTE. Provavelmente não é o que você quer (você quer por usuário, não é?) Tenho certeza que você tem algo como IDs de usuário, caso contrário, use o endereço IP estrangeiro , e ter um nome de arquivo exclusivo para cada usuário:

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

Você também pode definir um nome de arquivo de bloqueio para um grupo de operações. Maby o usuário pode fazer algumas coisas paralelas mas só esta operação dá problemas? Dê uma tag e inclua-a no nome do arquivo de bloqueio!

Esta prática realmente não é tão ruim e pode ser usada! Existem apenas pequenas maneiras de fazê-lo mais rápido (internos do mysql, segmentos de memória compartilhada, serialização em uma camada superior como balanceador de carga ...)

Com a solução postada acima, você pode fazer isso em seu aplicativo, o que provavelmente é bom. Você também pode usar o mesmo esquema no Mysql:http://dev.mysql.com/doc/refman/5.0/en/miscellaneous-functions.html#function_get-lock

Mas a implementação do PHP é provavelmente mais fácil e melhor para o seu caso de uso.

Se você realmente quer arrasar com uma solução ainda mais elegante, basta verificar esta função http://www.php.net/manual/en/function.sem-get.php