Моя база данных - SQL Server 2005/8. В системе бронирования у нас есть ограничение в 24 бронирования на событие. Этот код в хранимой процедуре проверяет:
- что текущий пользователь (@UserId) еще не зарегистрирован на событие (@EventsID)
- что текущее событие имеет текущий список бронирования до 24
- вставляет новое бронирование.
BEGIN TRANSACTION
IF (((select count (*) from dbo.aspnet_UsersEvents with (updlock)
where UserId = @UserId and EventsId = @EventsId) = 0)
AND ((SELECT Count(*) FROM dbo.aspnet_UsersEvents with (updlock)
WHERE EventsId = @EventsId) < 24))
BEGIN
insert into dbo.aspnet_UsersEvents (UserId, EventsId)
Values (@UserId, @EventsId)
END
COMMIT
Проблема в том, что это небезопасно. Два пользователя могут выполнить тест одновременно и сделать вывод, что они оба могут забронировать. Оба вставляют строку, и мы получаем 25 заказов.
Простое вложение в транзакцию не работает. Я попытался добавить WITH (UPDLOCK) к выборкам в надежде, что одна из них выполнит блокировку обновления и не допустит другую. Это не работает.