我的数据库是 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) 添加到选择中,希望其中一个会获取更新锁并将另一个锁在外面。那是行不通的。