Може да е полезно да разгледате как тази заявка всъщност се изпълнява от MySQL:
select * from tbl_codes where available = 1 order by rand() limit 1 for update
Това ще прочете и сортира всички редове, които съответстват на WHERE
условие, генерирайте произволно число с помощта на rand()
във виртуална колона за всеки ред, сортирайте всички редове (във временна таблица) въз основа на тази виртуална колона и след това върнете редове на клиента от сортирания набор до LIMIT
се достига (в този случай само един). FOR UPDATE
засяга заключването, извършено от целия израз, докато се изпълнява, и като такава клаузата се прилага, докато редовете се четат в рамките на InnoDB ,не тъй като се връщат на клиента.
Като оставим настрана очевидните последици за производителността от горното (това е ужасно), никога няма да получите разумно поведение при заключване от него.
Кратък отговор:
- Изберете реда, който искате, като използвате
RAND()
или всяка друга стратегия, която харесвате, за да намеритеPRIMARY KEY
стойност на този ред. Например:SELECT id FROM tbl_codes WHERE available = 1 ORDER BY rand() LIMIT 1
- Заключете реда, който искате, като използвате неговия
PRIMARY KEY
само. Например:SELECT * FROM tbl_codes WHERE id = N
Надяваме се, че това помага.