首先,我不需要100%防止死锁,但我能做些什么来减少它们会很好。
我有两张表Source
和Dest
。 Source中包含一系列唯一值,我需要从Source
请求新值,然后将其移至Dest
。
我有以下sql:
begin tran
declare @value
select top 1 @value = [value] from [source]
delete from [Source] where [value]=@value
insert into [Dest] ([Value]) values (@value)
select @value
commit tran
当多个用户获得相同的value
行时,偶尔会抛出死锁。我该如何预防/减少这种情况?
我正在使用SQL Server 2008
顺便说一句,我正在阅读/写作Source
和Dest
中的其他列。为简洁起见,这是一种简化。
由于
答案 0 :(得分:3)
您可以使用DELETE命令的OUTPUT子句来避免此竞争条件,因为它将从源中删除值并在单个原子操作中返回它。我制作了以下脚本来演示这个概念:
-- dummy data
CREATE TABLE #source (mycolumn INT);
CREATE TABLE #destination (mycolumn INT);
INSERT #source VALUES (1);
INSERT #source VALUES (2);
INSERT #source VALUES (3);
GO
-- stored procedure to demonstrate concept
CREATE PROCEDURE move
AS BEGIN
BEGIN TRANSACTION;
DECLARE @tmp TABLE (mycolumn INT);
DELETE TOP(1) #source OUTPUT DELETED.mycolumn INTO @tmp(mycolumn);
INSERT #destination (mycolumn) OUTPUT INSERTED.mycolumn
SELECT mycolumn
FROM @tmp;
COMMIT;
END
GO
-- testing
EXEC move;
GO -- remove from 1 from #source, insert 1 into #destination, returns 1
EXEC move;
GO -- remove from 2 from #source, insert 2 into #destination, returns 2
EXEC move;
GO -- remove from 3 from #source, insert 3 into #destination, returns 3
答案 1 :(得分:1)
您可以使用XLOCK
声明
SELECT
begin tran
declare @value
select top 1 @value = [value] from [source] with (XLOCK)
delete from [Source] where [value]=@value
insert into [Dest] ([Value]) values (@value)
select @value
commit tran