Атомарные операции MySQL и блокировка таблицы
у меня есть веб-сайт, где пользователи могут приобрести билеты, но количество билетов обычно ограничено и быстро. Я пытаюсь реализовать систему условного депонирования, чтобы пользователь мог щелкнуть, чтобы они хотели x количество билетов, и в этот момент я помещу их в состояние условного депонирования. Это дает им несколько минут, чтобы ввести информацию о своей кредитной карте и завершить покупку.
у меня есть три соответствующие таблицы: события, билеты и депозит. Строка в таблице событий описывает само мероприятие, включая максимальное количество доступных билетов.
таблица билетов содержит следующее:
ид_пользователя пользователь, который приобрел авиабилеты
number_of_tickets: сколько билетов они купили
код_события: соответствующее событие
таблица условного депонирования содержит следующее:
ид_пользователя пользователь в процессе покупки билеты
number_of_tickets: сколько билетов они хотят
код_события: соответствующее событие
В настоящее время я делаю три запроса MySQL, один для максимальных билетов, один для количества проданных билетов и один для количества билетов уже в escrow. Потом подсчитываю:
$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
после другой пользователь уже прочитал количество билетов уже в escrow, возможно, что я буду перепродавать шоу.
я использую движок InnoDB для своих таблиц, и я прочитал, как заблокировать одну строку с помощью SELECT .... FOR UPDATE
, но я не обновляю ни одной строки. The beginEscrow
функция просто вставит новую строку в таблицу условного депонирования. Я вычисляю $tickets_in_escrow
читая все строки с правильным идентификатор события и суммируя количество билетов в каждом из их.
может быть, я все делаю неправильно?
мне нужно заблокировать всю таблицу?
Я не могу быть первым, кто напишет систему депонирования билетов. Я загуглил себя до смерти, пытаясь найти какой-то учебник по такого рода вещам, но вычеркнул. Любые идеи были бы полезны.
спасибо!
1 ответов
вы очень близки по своему дизайну, но не совсем там.
прежде всего, ваша таблица событий должна содержать количество билетов, доступных для вашего мероприятия (в дополнение к тому, что вы хотите там).
во-вторых, в таблице условного депонирования должен быть столбец DATETIME, указывающий, когда срок действия условного депонирования истекает. Вы должны установить это значение всякий раз, когда билеты идут в escrow.
В-третьих, транзакция сдачи билетов в escrow должна
- заблокировать строку событий.
- прочитайте столбец доступные билеты. (прервать, если недостаточно доступны)
- вставьте строку в таблицу условного депонирования
- обновите строку события, чтобы уменьшить столбец доступные билеты.
- разблокировать строку событий.
В-четвертых, действие завершения продажи должно удалить строку условного депонирования и вставить строку проданного билета. Это не трудно.
В-пятых, вам нужно escrow операция очистки. Это должно искать все строки условного депонирования, которые истекли (которые имеют дату истечения срока действия в прошлом), и для каждого из них:
- заблокировать соответствующую строку событий.
- прочитайте количество депонированных билетов из таблицы депонирования
- удалить строку таблицы условного депонирования.
- обновите строку события, чтобы увеличить столбец доступные билеты.
- разблокировать строку событий.
фокус в том, чтобы количество из скачать билеты поддерживаются таким образом, чтобы правильно блокировать, поэтому условия гонки между пользователями не перепродают ваше мероприятие.