Mysql
 sql >> Database >  >> RDS >> Mysql

Impedisci transazioni simultanee in un'applicazione web

Sono contento che ti rendi conto che è solo una soluzione temporanea e cattiva e dovresti ottimizzare il tuo codice. Dimentica i tuoi token e cose. Il modo più semplice ed efficiente è probabilmente quello di avere un blocco file esclusivo su un file condiviso per operazione. Puoi immaginarlo come un pezzo di legno e solo uno può contenere l'id e solo chi lo tiene può parlare o fare qualcosa.

<?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 esegui questo script 10 volte parallelamente, ci vorranno 10 minuti per terminare (perché c'è solo un letto disponibile!) e vedrai l'eco "Ora ho dormito..." ogni 60 secondi (circa).

Questo serializza TUTTE le esecuzioni di questo codice GLOBALLY. Questo probabilmente non è quello che vuoi (lo vuoi per utente, vero?) Sono sicuro che hai qualcosa come User-ID, altrimenti usa l'indirizzo IP esterno e hanno un nome file univoco per ogni utente:

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

È inoltre possibile definire un nome file di blocco per un gruppo di operazioni. Forse l'utente può fare alcune cose in parallelo ma solo questa operazione crea problemi? Dagli un tag e includilo nel nome del file di blocco!

Questa pratica non è poi così male e può essere utilizzata! Ci sono solo piccoli modi per farlo più velocemente (interni mysql, segmenti di memoria condivisa, serializzazione su un livello superiore come il bilanciamento del carico...)

Con la soluzione pubblicata sopra puoi farlo nella tua applicazione che probabilmente è buona. Puoi usare lo stesso schema anche in Mysql:http://dev.mysql.com/doc/refman/5.0/en/funzioni-varie.html#function_get-lock

Ma l'implementazione di PHP è probabilmente più semplice e migliore per il tuo caso d'uso.

Se vuoi davvero prendere a calci in culo una soluzione ancora più elegante, dai un'occhiata a questa funzione http://www.php.net/manual/en/function.sem-get.php