Sql server 以队列格式处理表数据
下面是SP代码的主要部分,我正在使用该代码以FIFO队列顺序处理表数据。SP可以同时被100个进程调用Sql server 以队列格式处理表数据,sql-server,tsql,Sql Server,Tsql,下面是SP代码的主要部分,我正在使用该代码以FIFO队列顺序处理表数据。SP可以同时被100个进程调用 create TABLE #STAG(ident BIGINT) begin try begin tran insert into CaseLock (id,locktime,sessionid,lockid) output inserted.id into #STAG select top 1 i.ident
create TABLE #STAG(ident BIGINT)
begin try
begin tran
insert into CaseLock (id,locktime,sessionid,lockid) output inserted.id into #STAG
select top 1
i.ident
,getutcdate()
,case when @sess is null then i.sessionid else @sess end
,newid()
from QueueItem i WITH (ROWLOCK, READPAST) where
not exists(select 1 from CaseLock lck WITH (ROWLOCK, READPAST) where lck.id = i.ident)
and i.QUEUEIDENT = @QUEUEIDENT
and i.finished is null and (i.deferred is null or i.deferred < getutcdate())
commit
end try
begin catch
rollback
end catch
Select i.encryptid, i.id, i.ident, i.keyvalue, i.data, i.status, i.attempt
from QueueItem i WITH (ROWLOCK, READPAST)
where EXISTS(SELECT 1 FROM #STAG WHERE [#STAG].[ident]=i.ident)
QueueItem表中的数据无法删除,我们使用CaseLock表锁定已选择处理的记录。处理记录后,完成的列将更新为当前日期时间
我越来越
违反主键约束“PK_CaseLock”。无法插入
对象“dbo.CaseLock”中存在重复密钥。重复的键值为
105
我的问题是SP必须始终返回数据,如果SP未返回任何数据,应用程序将崩溃
如何修改代码以解决主键冲突错误并返回记录?在两个单独的会话ssms查询窗口中执行以下操作:
declare @QUEUEIDENT = 12345 --a queue value which has rows for processing
begin transaction
select top 1
i.ident
from QueueItem i WITH (ROWLOCK, READPAST) where
not exists(select 1 from CaseLock lck WITH (ROWLOCK, READPAST) where lck.id = i.ident)
and i.QUEUEIDENT = @QUEUEIDENT
and i.finished is null and (i.deferred is null or i.deferred < getutcdate())
..假设您在队列项目处理失败时从caselock中删除行,这些队列项目需要稍后重试,您可能会遇到一个队列读取器尝试插入其caselock在航班上的项目以删除读取器Reads在已删除行上释放任何caselock锁
为了解决这两个可能的问题,您可以尝试在读取和检查CaseLock时保持QueueItem上的锁,而不使用任何锁:
UPDLOCK on QueueItem keeps the lock for the duration of the transaction,
NOLOCK on CaseLock makes sure that i.ident will NEVER be inserted if it exists
``
如果希望保留现有实现,请根据另一个表检查队列项处理状态。
更简单的方法是在QueueItem上有一个与流程相关的列,并使用READPAST依次捕获inserted.ident等更新该列。感谢您的帮助UPDLOCK提供了帮助。我将尝试您建议的第二种方法,并比较两种方法的性能。是否会对性能产生任何影响?诺洛克可能会更快一点。NOLOCK on CaseLock的建议是为了确保一个进程不会两次插入同一个CaseLock。
UPDLOCK on QueueItem keeps the lock for the duration of the transaction,
NOLOCK on CaseLock makes sure that i.ident will NEVER be inserted if it exists
... from QueueItem i WITH (ROWLOCK, UPDLOCK, READPAST)
where
not exists(select 1 from CaseLock lck WITH (NOLOCK) where lck.id = i.ident)...