Puede ser útil ver cómo MySQL ejecuta realmente esta consulta:
select * from tbl_codes where available = 1 order by rand() limit 1 for update
Esto leerá y clasificará todas las filas que coincidan con WHERE
condición, generar un número aleatorio usando rand()
en una columna virtual para cada fila, ordene todas las filas (en una tabla temporal) en función de esa columna virtual y luego devuelva las filas al cliente desde el conjunto ordenado hasta el LIMIT
se alcanza (en este caso sólo uno). El FOR UPDATE
afecta el bloqueo realizado por toda la declaración mientras se ejecuta y, como tal, la cláusula se aplica a medida que se leen las filas dentro de InnoDB , no a medida que se devuelven al cliente.
Dejando a un lado las obvias implicaciones de rendimiento de lo anterior (es terrible), nunca obtendrá un comportamiento de bloqueo razonable.
Respuesta corta:
- Seleccione la fila que desee, usando
RAND()
o cualquier otra estrategia que desee, para encontrar laPRIMARY KEY
valor de esa fila. Ej.:SELECT id FROM tbl_codes WHERE available = 1 ORDER BY rand() LIMIT 1
- Bloquee la fila que desee usando su
PRIMARY KEY
solamente. Por ejemplo:SELECT * FROM tbl_codes WHERE id = N
Espero que eso ayude.