循环流程队列上的SQL Server竞争条件

时间:2018-02-07 18:47:28

标签: sql sql-server entity-framework race-condition

TL; DR

循环进程队列上的SQL Server争用条件,尽管将ROWLOCKREADPASTUPDLOCK提示与应用程序锁一起添加。

我有一个应用程序,其中多个应用程序服务器和多个进程运行" jobs"存储在SQL Server 2014数据库中的类似队列的表中。每隔x秒,每个进程查询表以查找要运行的新作业(如果该进程可用于执行作业)。需要在用户到用户的基础上以循环方式分配新的工作。问题是我当前的查询遇到竞争条件,因此多个进程作用于同一作业,导致输出表中出现重复的数据集。这是当前查询的样子:

EXEC sp_getapplock @Resource = 'GetJobAssignments', @LockMode = 'Exclusive', @LockOwner = 'Session';
BEGIN TRANSACTION;
    WITH cte AS
    (
    SELECT TOP (@nMaxJobs) [JobId]
        ,[Owner]
        ,[Timeout]
        ,[StartTime]
        ,[Status]
        ,[userID] 
        , ROW_NUMBER() OVER (PARTITION BY [userID] ORDER BY [JobID]) AS [recID] 
    FROM [Jobs]
    WITH (ROWLOCK, READPAST, UPDLOCK)
    WHERE [Status] = 0 AND [Owner] is null
    ORDER BY [recID], [userID]
    )
    UPDATE cte SET [Owner] = @owner, [Status] = 1;
COMMIT;
EXEC sp_releaseapplock @Resource = 'GetJobAssignments', @LockOwner = 'Session';

我尝试了ROWLOCKREADPASTUPDLOCKXLOCK的各种组合,但没有运气。在SessionTransaction设置中也可以使用和不使用applock。在查询的其他迭代中,我把事务隔离级别放到REPEATABLE READSERIALIZABLE,并且没有成功。

请记住,我既不是SQL也不是SQLServer专家,下一部分可能没有任何意义......我尝试在存储过程中执行此操作(就像现在一样),但在过去它也有使用dbContext.Database.ExecuteSqlCommand()从EF5调用(它现在只是一个存储过程,是dbContext的一部分)。

这个当前的查询是对几个类似于此的问题的已知工作答案的混淆:

SQL Server Process Queue Race Condition

https://dba.stackexchange.com/questions/81791/strategies-for-checking-out-records-for-processing

除了我在这里提到的事情的基础研究之外,我对SQL Server中的策略非常不熟悉,以防止死锁/竞争条件。我可以在我的查询中尝试其他任何选项,或者是否存在可以检查的任何已知先决条件,这会阻止当前策略的运行?

0 个答案:

没有答案