Атомарные операции 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 должна

  1. заблокировать строку событий.
  2. прочитайте столбец доступные билеты. (прервать, если недостаточно доступны)
  3. вставьте строку в таблицу условного депонирования
  4. обновите строку события, чтобы уменьшить столбец доступные билеты.
  5. разблокировать строку событий.

В-четвертых, действие завершения продажи должно удалить строку условного депонирования и вставить строку проданного билета. Это не трудно.

В-пятых, вам нужно escrow операция очистки. Это должно искать все строки условного депонирования, которые истекли (которые имеют дату истечения срока действия в прошлом), и для каждого из них:

  1. заблокировать соответствующую строку событий.
  2. прочитайте количество депонированных билетов из таблицы депонирования
  3. удалить строку таблицы условного депонирования.
  4. обновите строку события, чтобы увеличить столбец доступные билеты.
  5. разблокировать строку событий.

фокус в том, чтобы количество из скачать билеты поддерживаются таким образом, чтобы правильно блокировать, поэтому условия гонки между пользователями не перепродают ваше мероприятие.