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 KEY
zu 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 KEY
nur. Beispiel:SELECT * FROM tbl_codes WHERE id = N
Hoffentlich hilft das.