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 KEY
valor dessa linha. Ex.:SELECT id FROM tbl_codes WHERE available = 1 ORDER BY rand() LIMIT 1
- Bloqueie a linha desejada usando sua
PRIMARY KEY
só. Por exemplo:SELECT * FROM tbl_codes WHERE id = N
Espero que isso ajude.