Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 以队列格式处理表数据_Sql Server_Tsql - Fatal编程技术网

Sql server 以队列格式处理表数据

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

下面是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
        ,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)...