Může být užitečné podívat se, jak tento dotaz ve skutečnosti provádí MySQL:
select * from tbl_codes where available = 1 order by rand() limit 1 for update
To přečte a seřadí všechny řádky, které odpovídají WHERE
podmínku, vygenerujte náhodné číslo pomocí rand()
do virtuálního sloupce pro každý řádek, seřaďte všechny řádky (v dočasné tabulce) na základě tohoto virtuálního sloupce a poté vraťte řádky klientovi z seřazené sady až do LIMIT
je dosaženo (v tomto případě pouze jeden). FOR UPDATE
ovlivňuje zamykání provedené celým příkazem během jeho provádění a jako taková se klauzule použije při čtení řádků v rámci InnoDB , ne jak jsou vráceny klientovi.
Když pomineme zjevné důsledky výše uvedeného na výkon (je to hrozné), nikdy z toho nedostanete rozumné chování při zamykání.
Krátká odpověď:
- Vyberte požadovaný řádek pomocí
RAND()
nebo jakoukoli jinou strategii, kterou chcete, abyste našliPRIMARY KEY
hodnotu toho řádku. Např.:SELECT id FROM tbl_codes WHERE available = 1 ORDER BY rand() LIMIT 1
- Zamkněte požadovaný řádek pomocí jeho
PRIMARY KEY
pouze. Např.:SELECT * FROM tbl_codes WHERE id = N
Snad to pomůže.