我知道输出参数不能保证并行逻辑。我想要实现的逻辑在多线程环境中失败了。
要对此进行测试,只需打开 2 个窗口并尽可能快地并排执行它们。然后比较Ids,有些会重复。
declare @id int
select @id = 1
while @id >=1 and @id <= 100
begin
UPDATE sys_QueueJob
SET StartedOn = GETDATE()
OUTPUT DELETED.Id as Result
WHERE Id = (select top 1 qj.Id
from sys_QueueJob qj
where qj.ProcessedOn is null AND qj.StartedOn is null
order by CreatedOn asc)
print 'Count: ' + convert(nvarchar(max), @id)
select @id = @id + 1
end
我只想从尚未启动的 qeueJob 表中获取最旧的条目,同时告诉它现在已经启动了。并且相同的代码需要为我提供 100% 的确定性,即下一次执行会给我下一个正确的 Id。
我怎样才能做到这一点?
虽然我同意“sp_getapplock/sp_releaseapplock 方法 [是] 管理显式信号量逻辑的最直接和最不脏的方法”。
有一个不起作用的原因以及一种直接修复它的方法,并启用多个并发事务以同时获取不相交的行:
这应该解决它:
请参阅将表用作队列