用于批量更新的sql锁定

用于批量更新的sql锁定,sql,transactions,locking,sql-server-2008-r2,Sql,Transactions,Locking,Sql Server 2008 R2,我正在使用SQLServer2008R2和C 我正在SQL Server中插入一批列状态设置为值p的行。 之后,我检查有多少行已经具有状态R,如果少于20行,我将该行更新为状态R。 插入和更新时,会不断添加和更新更多行 我尝试了多种方式的事务和锁定,但仍然是:在激活新批处理的那一刻,有20多行的状态为R,持续几毫秒。在那几毫秒之后,它稳定回到20 有人知道为什么在爆炸时锁似乎不起作用吗? 示例代码,原因,你能分享的关于这个主题的任何东西都是有用的! 谢谢 以下是我的存储过程: DEC

我正在使用SQLServer2008R2和C

我正在SQL Server中插入一批列状态设置为值p的行。 之后,我检查有多少行已经具有状态R,如果少于20行,我将该行更新为状态R。 插入和更新时,会不断添加和更新更多行

我尝试了多种方式的事务和锁定,但仍然是:在激活新批处理的那一刻,有20多行的状态为R,持续几毫秒。在那几毫秒之后,它稳定回到20

有人知道为什么在爆炸时锁似乎不起作用吗? 示例代码,原因,你能分享的关于这个主题的任何东西都是有用的! 谢谢

以下是我的存储过程:

      DECLARE @return BIT 
      SET @return = -1 
      DECLARE @previousValue INT 
      --insert the started orchestration 
      INSERT INTO torchestrationcontroller WITH (ROWLOCK)
                ([flowname],[orchestrationid],[status]) 
                VALUES      (@FlowName, @OrchestrationID, 'P') 

      --check settings 
      DECLARE @maxRunning INT 

      SELECT @maxRunning = maxinstances 
              FROM   torchestrationflows WITH (NOLOCK) 
              WHERE  [flowname] = @FlowName 

      --if running is 0, than you can pass, no limitation here                
       IF( @maxRunning = 0 ) 
        BEGIN 
            SET @return = 1 

            UPDATE torchestrationcontroller WITH(ROWLOCK) 
                    SET    [status] = 'R' 
                    WHERE  [orchestrationid] = @OrchestrationID 
        END 
      ELSE 
        --  BEGIN 


RETRY: -- Label RETRY
BEGIN TRY
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRANSACTION T1

        --else: check how many orchestrations are now running 
        --start lock table 
        DECLARE @currentRunning INT 

      SELECT @currentRunning = Count(*) 
              FROM   torchestrationcontroller WITH (TABLOCKX) --Use an exclusive lock that will be held until the end of the transaction on all data processed by the statement
              WHERE  [flowname] = @FlowName 
              AND [status] = 'R'                  
              --CASE

      IF( @currentRunning < @maxRunning ) 
        BEGIN 
            -- less orchestrations are running than allowed 
            SET @return = 1 

            UPDATE torchestrationcontroller WITH(TABLOCKX) 
            SET    [status] = 'R' 
            WHERE  [orchestrationid] = @OrchestrationID 
        END 
      ELSE 
        -- more or equal orchestrations are running than allowed 
        SET @return = 0 

      --end lock table 
      SELECT @Return 

COMMIT TRANSACTION T1
END TRY
BEGIN CATCH
--PRINT 'Rollback Transaction'
ROLLBACK TRANSACTION
IF ERROR_NUMBER() = 1205 -- Deadlock Error Number
BEGIN

    WAITFOR DELAY '00:00:00.05' -- Wait for 5 ms
    GOTO RETRY -- Go to Label RETRY
END
END CATCH

我已经能够通过在树存储过程上设置隔离级别serializable+transaction来解决这个问题,其中两个我没有提到,因为我认为它们对这个问题不重要。显然,是多个存储进程的组合相互干扰


如果你知道一个更好的方法来修复它,可以给我一个更好的性能,请让我知道

显然,如果两个线程同时读取计数,然后继续更新,行数可能会超过20。一些示例代码可以帮助诊断具体情况。我已经添加了我的代码,希望您能在这方面提供更多帮助。我以为问题就像你说的,但有办法解决吗?我认为隔离级别可能会有所帮助。maxRunning=0的免费通行证似乎有点可疑。。。50个线程可能会读取该信息,然后更新50行