Атомарные операции MySQL и блокировка таблиц
У меня есть веб-сайт, где пользователи могут покупать билеты, но количество билетов обычно ограничено и идет быстро. Я пытаюсь внедрить систему условного депонирования, чтобы пользователь мог щелкнуть мышью, чтобы получить х количество билетов, и тогда я переведу их в условное депонирование. Это дает им несколько минут для ввода информации о своей кредитной карте и завершения покупки.
У меня есть три соответствующие таблицы: события, билеты и условное депонирование. Строка в таблице событий описывает само событие, включая максимальное количество доступных билетов.
Таблица билетов содержит следующее:
user_id: пользователь, который купил билеты
number_of_tickets: сколько билетов они купили
event_id: соответствующее событие
Таблица условного депонирования содержит следующее:
user_id: пользователь в процессе покупки билетов
number_of_tickets: сколько билетов они хотят
event_id: соответствующее событие
В настоящее время я делаю три запроса MySQL: один для определения максимального количества билетов, один для количества проданных билетов и один для количества билетов, которые уже находятся на условном депонировании. Затем я рассчитываю:
$remaining_tickets = $max_tickets - $tickets_sold - $tickets_in_escrow;
if ($remaining_tickets >= $tickets_desired)
{
beginEscrow($user_id, $event_id, $tickets_desired);
}
else
{
echo "Error: not enough ticket remain.";
}
Моя проблема в том, что более чем один пользователь может выполнять этот код одновременно. Если бы один пользователь позвонилbeginEscrow
after другой пользователь уже прочитал количество билетов уже в условном депонировании, возможно, я перепродал шоу.
Я использую движок InnoDB для своих таблиц и прочитал, как заблокировать одну строку с помощьюSELECT .... FOR UPDATE
, но я не обновляю ни одной строки.beginEscrow
Функция просто вставит новую строку в таблицу условного депонирования. Я рассчитываю$tickets_in_escrow
читая все строки с правильным идентификатором события и складывая количество билетов в каждом из них.
Может быть, я все делаю неправильно?
Нужно ли блокировать всю таблицу?
Я не могу быть первым, кто написал систему условного депонирования билетов. Я погуглил себя до смерти, пытаясь найти какой-нибудь учебник по этому виду вещей, но вычеркнул. Любые идеи будут полезны.
Спасибо!