Должен ли я использовать select_for_update в моем приложении django с базой данных postgresql?

#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 выполняет фактическую блокировку.