Es kann nützlich sein, sich anzusehen, wie diese Abfrage tatsächlich von MySQL ausgeführt wird:
select * from tbl_codes where available = 1 order by rand() limit 1 for update
Dadurch werden alle Zeilen gelesen und sortiert, die mit WHERE übereinstimmen Bedingung, generieren Sie eine Zufallszahl mit rand() in eine virtuelle Spalte für jede Zeile, sortieren Sie alle Zeilen (in einer temporären Tabelle) basierend auf dieser virtuellen Spalte und geben Sie dann Zeilen aus der sortierten Menge bis zum LIMIT an den Client zurück erreicht ist (in diesem Fall nur eine). Der FOR UPDATE wirkt sich auf das Sperren der gesamten Anweisung während der Ausführung aus, und als solche wird die Klausel angewendet, wenn Zeilen innerhalb von InnoDB gelesen werden , nicht wie sie an den Client zurückgegeben werden.
Abgesehen von den offensichtlichen Auswirkungen auf die Leistung (es ist schrecklich), werden Sie niemals ein vernünftiges Sperrverhalten erzielen.
Kurze Antwort:
- Wählen Sie die gewünschte Zeile mit
RAND()aus oder jede andere Strategie, die Sie mögen, um denPRIMARY KEYzu finden Wert dieser Zeile. Beispiel:SELECT id FROM tbl_codes WHERE available = 1 ORDER BY rand() LIMIT 1 - Sperren Sie die gewünschte Zeile mit ihrem
PRIMARY KEYnur. Beispiel:SELECT * FROM tbl_codes WHERE id = N
Hoffentlich hilft das.