Как решить проблему конкурентного бронирования при переходе на реальную базу данных?
Ответ от нейросети
sobes.tech AI
Проблема конкурентного бронирования при работе с реальной базой данных решается с помощью механизмов транзакций и блокировок, чтобы избежать состояния гонки и двойного бронирования.
Основные подходы:
-
Оптимистичная блокировка: в таблице добавляется поле версии (version) или timestamp. При обновлении записи проверяется, что версия не изменилась с момента чтения. Если изменилась — операция откатывается и повторяется.
-
Пессимистичная блокировка: при попытке бронирования строка блокируется (например,
SELECT ... FOR UPDATE), чтобы другие транзакции не могли её изменить до завершения текущей. -
Транзакции с уровнем изоляции SERIALIZABLE: гарантируют, что параллельные транзакции выполняются как последовательные, предотвращая конфликты.
Пример с использованием пессимистичной блокировки в Go с PostgreSQL:
func BookSlot(db *sql.DB, slotID int) error {
tx, err := db.Begin()
if err != nil {
return err
}
defer tx.Rollback()
var available bool
err = tx.QueryRow("SELECT available FROM slots WHERE id = $1 FOR UPDATE", slotID).Scan(&available)
if err != nil {
return err
}
if !available {
return errors.New("слот уже забронирован")
}
_, err = tx.Exec("UPDATE slots SET available = false WHERE id = $1", slotID)
if err != nil {
return err
}
return tx.Commit()
}
Такой подход гарантирует, что одновременно только одна транзакция сможет забронировать слот.