2012-11-06 21 views
6

Sto lavorando su un sistema di punti che darà agli utenti del mio sito una classifica basata sui loro punti, sto dando all'utente +1 punti ogni volta che qualcuno controlla la sua pagina del profilo. Diciamo che l'utente ha 200 punti, nello stesso identico momento in cui 10 utenti hanno controllato la sua pagina profilo, dal mio intendimento il codice otterrà 200 add 1 e il risultato sarà 200 + 1 = 201 se i 10 utenti sono nello stesso momento come agirà il database?Come aggiungere un numero ad un valore corrente in mysql (più volte allo stesso tempo)?

Logicamente conterà una sola visita perché il tempo in cui gli utenti hanno controllato il profilo era 200, quindi quando l'aggiornamento di MYSQL avviene sarà sempre 201. Sono corretto?

risposta

17

Se si seleziona il numero di punti esistente, aggiungerne uno nel client e quindi scrivere nuovamente il valore aggiornato nel database, quindi si dispone di un race condition. Come fai notare, è possibile che alcune visualizzazioni non vengano conteggiate.

Invece si dovrebbe cercare di utilizzare un aggiornamento atomica ed evitare il problema:

UPDATE user SET points = points + 1 WHERE id = 42 

Un'alternativa è quello di leggere con SELECT ... FOR UPDATE. Dalla documentation:

Se si utilizza FOR UPDATE con un motore di archiviazione che utilizza pagina o riga serrature, righe esaminate dalla query sono fino alla fine della transazione corrente bloccato scrittura. L'utilizzo di LOCK IN SHARE MODE imposta un blocco condiviso che consente ad altre transazioni di leggere le righe esaminate ma di non aggiornarle o eliminarle. Vedere Sezione 14.2.8.3, "SELEZIONA ... PER AGGIORNAMENTO e SELEZIONA ... BLOCCA IN MODALITÀ DI CONDIVISIONE Lettura di blocco"

Problemi correlati