Het kan handig zijn om te kijken hoe deze query daadwerkelijk wordt uitgevoerd door MySQL:
select * from tbl_codes where available = 1 order by rand() limit 1 for update
Hiermee worden alle rijen gelezen en gesorteerd die overeenkomen met de WHERE
voorwaarde, genereer een willekeurig getal met rand()
in een virtuele kolom voor elke rij, sorteer alle rijen (in een tijdelijke tabel) op basis van die virtuele kolom en retourneer vervolgens rijen naar de client van de gesorteerde set tot de LIMIT
is bereikt (in dit geval slechts één). De FOR UPDATE
heeft invloed op de vergrendeling die wordt gedaan door de hele instructie terwijl deze wordt uitgevoerd, en als zodanig wordt de clausule toegepast terwijl rijen worden gelezen binnen InnoDB , niet als ze worden teruggestuurd naar de klant.
Afgezien van de voor de hand liggende prestatie-implicaties van het bovenstaande (het is verschrikkelijk), zul je er nooit redelijk vergrendelingsgedrag van krijgen.
Kort antwoord:
- Selecteer de gewenste rij met
RAND()
of een andere strategie die je leuk vindt, om dePRIMARY KEY
. te vinden waarde van die rij. Bijvoorbeeld:SELECT id FROM tbl_codes WHERE available = 1 ORDER BY rand() LIMIT 1
- Vergrendel de gewenste rij met de
PRIMARY KEY
enkel en alleen. Bijv.:SELECT * FROM tbl_codes WHERE id = N
Hopelijk helpt dat.