← Все заметки

· 1 мин чтения

Двойная бронь: транзакция плюс частичный UNIQUE-индекс

Как booking-slots защищается от двух клиентов, которые одновременно записываются на одно время, и чем проверяется эта защита.

Проект: booking-slots

Классическая гонка: два клиента одновременно видят свободный слот и оба нажимают «записаться». Одной проверки «свободно ли» в коде недостаточно: между проверкой и вставкой может вклиниться второй запрос.

Первая линия: транзакция

В Book пересчёт свободных слотов и вставка записи выполняются в одной транзакции. Слот, которого нет среди свободных, даёт ErrTaken (или ErrPast, если время уже прошло).

Вторая линия: индекс

База сама не даст создать дубль:

CREATE UNIQUE INDEX IF NOT EXISTS ux_bookings_active_start
  ON bookings(date, start_min) WHERE status = 'active';

Индекс частичный: он действует только для активных записей, поэтому отменённая запись освобождает время. Если вставка упирается в индекс, код превращает ошибку в тот же ErrTaken, и клиент получает 409.

Чем проверено

Тест запускает 30 горутин на одно и то же время: успешной должна быть ровно одна запись.

Границы

Это защита от двойной брони одного ресурса: все услуги делят одно расписание, и модель с несколькими специалистами потребует другого индекса. Об этом сказано в ограничениях проекта.