#django #postgresql
Вопрос:
В настоящее время я создаю инструмент бронирования (django и postgresql), в котором люди бронируют места в определенном месте. Место имеет ограниченную вместимость, и поэтому может не хватить места, пока пользователь пытается забронировать место. Я предполагаю, что это может произойти, когда другой пользователь бронирует место немного раньше, чем текущий пользователь бронирует, например, если осталось только 1 место, другой пользователь тоже может забронировать, и база данных не сможет с этим справиться.
Поэтому мой вопрос в том, настоятельно ли вы советуете использовать select_for_update или есть что-то еще, что может помочь мне преодолеть эту проблему?
Ответ №1:
Да, это правильное использование select_for_update
. Вы заблокировали бы определенную строку местоположения (примените a filter
перед вызовом select_for_update
). Это означает, что одновременно можно забронировать 2 разных места, но если есть 2 бронирования для одного и того же места, которые происходят в одну и ту же секунду, они будут вызваны.
Это создает критический раздел, и вы можете быть уверены, что он не будет перекрываться с критическим разделом другого запроса. В критическом разделе вам нужно будет подтвердить, что выбранный временной интервал свободен — без этого проверка select_for_update
не будет иметь никакого эффекта.
Я мог бы представить себе другой подход, основанный на уникальных ограничениях, он не универсален, но может быть проще в реализации. Давайте представим, что вы бронируете ресурс на определенный день. У вас может быть «уникальная комбинация вместе» для resource_id
и date
. Последующее сохранение вызовет IntegrityError
, и вы сможете поймать его и сообщить пользователю, что ресурс был только что забронирован на выбранную дату.
Комментарии:
1. Большое вам спасибо @Snake9920, когда я использую
select_for_update
одну таблицу, она блокирует только эту или все остальные таблицы в базе данных?2. Это блокировка определенных строк (выбранных вами), а не целых таблиц. Я бы рекомендовал прочитать больше об этом в документах Postgres , поскольку Django просто добавляет предложение «ДЛЯ ОБНОВЛЕНИЯ» в SQL-запрос, а компонент database engine выполняет фактическую блокировку.