我有一张桌子
create table lastnum
(
id int,
num int
)
它有一行
Id num
1 101
2个用户同时执行相同的存储过程 - 存储过程是
declare @num int
set @num = (select num + 1 from lastnum where id = 1)
update lastnum
set num = @num
where Id = 1
return @num
命令在精确的微秒运行的可能性是什么,所以即使在两次调用之后,num的值也只有102
答案 0 :(得分:5)
该代码绝对可能“失败”并向两个用户提供相同的号码。
这是否真的可能在您的环境中发生取决于您的负载(如果此代码很少运行,您可能会侥幸逃脱)以及您的服务器配置方式。 Sql Server具有不同的Isolation Levels,您可以使用它来确定允许的潜在冲突程度。在最高隔离时,该代码是完全安全的(假设您的用户正在进行隐式事务)......但性能损失可能很严重。
Sql Server具有内置机制,您应该使用这些机制来避免这些潜在的冲突:即identity
列和scope_identity()
函数。较新版本的Sql Server也有 Sequences。
Locking hints或明确的交易也可能对您有所帮助......但我会尽量避免这些支持此答案中的其他选项。
答案 1 :(得分:0)
我不确定"可能的引擎盖"发生的事情是,但肯定是可能,这是因为在您计算新值的行和您更新值的行周围没有任何事务。
答案 2 :(得分:0)
输出子句可以做你需要的事情
declare @t table (id int primary key, num int);
insert into @t values (1, 101);
declare @n table (num int);
update @t
set num = num+1
output inserted.num into @n
where id = 1;
select num from @n;
答案 3 :(得分:0)
感谢Eric Brandt和Joel Coehoorn
解决方案是使用'序列' - 我认为SQL 2012以后的新内容