SQL(Microsoft) - 同时更新2个

时间:2018-03-06 14:19:09

标签: sql sql-server

我有一张桌子

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

4 个答案:

答案 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以后的新内容