Det kan vara användbart att titta på hur denna fråga faktiskt exekveras av MySQL:
select * from tbl_codes where available = 1 order by rand() limit 1 for update
Detta kommer att läsa och sortera alla rader som matchar WHERE
villkor, generera ett slumptal med rand()
i en virtuell kolumn för varje rad, sortera alla rader (i en temporär tabell) baserat på den virtuella kolumnen och returnera sedan rader till klienten från den sorterade uppsättningen tills LIMIT
nås (i detta fall bara en). FOR UPDATE
påverkar låsning som görs av hela satsen medan den körs, och som sådan tillämpas satsen när rader läses inom InnoDB , inte när de returneras till klienten.
Bortsett från de uppenbara prestandakonsekvenserna av ovanstående (det är fruktansvärt), kommer du aldrig att få rimligt låsbeteende av det.
Kort svar:
- Välj den rad du vill använda med
RAND()
eller någon annan strategi du gillar, för att hitta denPRIMARY KEY
värdet på den raden. T.ex.:SELECT id FROM tbl_codes WHERE available = 1 ORDER BY rand() LIMIT 1
- Lås raden du vill använda med dess
PRIMARY KEY
endast. T.ex.:SELECT * FROM tbl_codes WHERE id = N
Förhoppningsvis hjälper det.