Pode ser útil ver como essa consulta é realmente executada pelo MySQL:
select * from tbl_codes where available = 1 order by rand() limit 1 for update
Isso lerá e classificará todas as linhas que correspondem ao
WHERE condição, gere um número aleatório usando rand() em uma coluna virtual para cada linha, classifique todas as linhas (em uma tabela temporária) com base nessa coluna virtual e, em seguida, retorne as linhas para o cliente do conjunto classificado até o LIMIT é alcançado (neste caso apenas um). O FOR UPDATE afeta o bloqueio feito por toda a instrução durante a execução e, como tal, a cláusula é aplicada à medida que as linhas são lidas dentro do InnoDB , não à medida que são devolvidos ao cliente. Deixando de lado as implicações óbvias de desempenho acima (é terrível), você nunca obterá um comportamento de bloqueio razoável.
Resposta curta:
- Selecione a linha desejada usando
RAND()ou qualquer outra estratégia de sua preferência, para encontrar aPRIMARY KEYvalor dessa linha. Ex.:SELECT id FROM tbl_codes WHERE available = 1 ORDER BY rand() LIMIT 1 - Bloqueie a linha desejada usando sua
PRIMARY KEYsó. Por exemplo:SELECT * FROM tbl_codes WHERE id = N
Espero que isso ajude.