sql锁定批量更新

时间:2012-12-06 10:37:31

标签: sql transactions locking sql-server-2008-r2

我正在使用SQL Server 2008 R2和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

1 个答案:

答案 0 :(得分:0)

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

如果你知道更好的解决方法,可以让我有更好的表现,请告诉我!