要在SQL Server 2012中为我的一个更新任务实现多线程,我需要让不同的线程从表(Accounts)中选择一行,并使用存储过程中的更新将该行标记为已处理。
这样的事情:
create procedure ChooseNextAccountToProcess (@Account_ID Int Output)
select top 1 @Account_ID = Account_ID
from Accounts
order by LastProcessDate Desc
update Accounts
set LastProcessDate = getdate()
where Account_ID = @Account_ID
go
这种方法的问题是两个线程可能同时完全调用此存储过程并处理同一个帐户。我的目标是从帐户表中选择一个帐户,并在更新有机会更新帐户之前将其独占锁定。
我尝试了SELECT .... WITH (UPDLOCK)
和WITH Exclusive lock
但是当我选择该行时,这些都不能实际上对该行进行排他锁定。
有什么建议吗?
答案 0 :(得分:0)
您可以使用update top (n) ...
,但不能直接在语句中指定order by
。所以,一个小技巧是有序的:
declare @t table (
Id int primary key,
LastProcessDate date not null
);
insert into @t (Id, LastProcessDate)
values
(1, getdate() - 10),
(2, getdate() - 7),
(3, getdate() - 1),
(4, getdate() - 4);
-- Your stored procedure code starts from here
declare @res table (Id int primary key);
declare @AccountId int;
update a set LastProcessDate = getdate()
output inserted.Id into @res(Id)
from (select top (1) * from @t order by LastProcessDate desc) a;
select @AccountId = Id from @res;
-- Returns 3
select @AccountId;
不完全是单行,但接近它,是的。