Può essere utile osservare come questa query viene effettivamente eseguita da MySQL:
select * from tbl_codes where available = 1 order by rand() limit 1 for update
Questo leggerà e ordinerà tutte le righe che corrispondono a WHERE
condizione, genera un numero casuale usando rand()
in una colonna virtuale per ogni riga, ordina tutte le righe (in una tabella temporanea) in base a quella colonna virtuale, quindi restituisci le righe al client dal set ordinato fino al LIMIT
viene raggiunto (in questo caso solo uno). Il FOR UPDATE
influisce sul blocco eseguito dall'intera istruzione durante l'esecuzione e, in quanto tale, la clausola viene applicata quando le righe vengono lette all'interno di InnoDB , non man mano che vengono restituiti al cliente.
Mettendo da parte le ovvie implicazioni sulle prestazioni di cui sopra (è terribile), non otterrai mai un comportamento di blocco ragionevole da esso.
Risposta breve:
- Seleziona la riga che desideri, utilizzando
RAND()
o qualsiasi altra strategia di tuo gradimento, per trovare laPRIMARY KEY
valore di quella riga. Es.:SELECT id FROM tbl_codes WHERE available = 1 ORDER BY rand() LIMIT 1
- Blocca la riga che desideri utilizzando la sua
PRIMARY KEY
solo. Es.:SELECT * FROM tbl_codes WHERE id = N
Spero che questo aiuti.