Iam*_*mIC 14 sql-server concurrency locking sql-server-2008
编辑:我的问题是,"为什么我的第一个代码示例有效?" 请继续阅读......
编辑1:毫无疑问,唯一约束是确保不会发生重复的正确方法.这是给定的.但是,有时我们需要知道我们正在尝试重复输入.此外,这篇文章不仅仅是处理重复.
这可能是对SO的100多个问题的重复.我已经阅读了关于原子更新,锁和并发的简单问题的无穷无尽的混淆和矛盾.
我看到博客和专家在这些方面存在广泛的分歧.在这里,我根据人们建议的各种解决方案提供测试代码,指出结果,陈述我的观点,并邀请您的评论.
上下文:我正在运行SQL Server 2008 Express SP2.
我创建了以下测试表:
create table dbo.Temp (Col int)
Run Code Online (Sandbox Code Playgroud)
由于我们想要测试SQL代码的想法而不是约束,因此该表故意不对其进行约束.
我在2个然后3个查询窗口中同时运行以下命令:
declare @i int
set @i = 0
while @i < 5000 begin
set @i = @i + 1
update dbo.temp set Col = (SELECT Col from dbo.Temp) + 1
end
Run Code Online (Sandbox Code Playgroud)
我可以看到,我没有使用任何显式锁定.所有数据库设置均为默认值 我检查了Col的值,它是所需的数字:25,000.没有错过.
由于SQL Server是ACID,"A"告诉我们单个语句是以原子方式执行的.因此,基于上述内容,我们可以同意那些说如上所述的简单更新不需要锁定的人.
接下来,我在3个查询窗口中同时运行以下命令:
while @i < 5000 begin
set @i = @i + 1
insert into dbo.temp select @i where not exists
(select 1 from dbo.temp where Col = @i)
end
Run Code Online (Sandbox Code Playgroud)
尽管这是一个陈述,但结果并不正确.缺少值,重复值和> 5k行.
接下来,我在3个查询窗口中同时运行以下流行的解决方案:
declare @i int
set @i = 0
while @i < 5000 begin
set @i = @i + 1
insert into dbo.temp select @i where not exists
(select 1 from dbo.temp with (updlock) where Col = @i)
end
Run Code Online (Sandbox Code Playgroud)
结果不正确.缺少值,重复值和> 5k行.
接下来,对于那些怀疑SQL Server隐式包装事务中的单个语句(在ACID中称为"A")的人:
declare @i int
set @i = 0
while @i < 5000 begin
set @i = @i + 1
begin tran
insert into dbo.temp select @i where not exists
(select 1 from dbo.temp with (updlock) where Col = @i)
commit tran
end
Run Code Online (Sandbox Code Playgroud)
同样不正确的结果.
接下来,我在3个查询窗口中同时运行以下命令:
declare @i int
set @i = 0
while @i < 5000 begin
set @i = @i + 1
insert into dbo.temp select @i where not exists
(select 1 from dbo.temp with (XLOCK, ROWLOCK) where Col = @i)
end
Run Code Online (Sandbox Code Playgroud)
这很有效.仅限5k唯一值.
接下来,以下3个窗口:
declare @i int
set @i = 0
while @i < 5000 begin
set @i = @i + 1
merge dbo.temp as t
using (select @i) as test (Col)
ON (t.Col = test.Col)
when not matched then
insert values (@i);
end
Run Code Online (Sandbox Code Playgroud)
这很有效.仅限5k唯一值.
我的结论是:
请亲自测试一下.
现在,有人可以向我解释为什么我的第一个例子有效吗?:-)