2012-12-06 117 views
0

我正在使用SQL Server 2008 R2和C#。SQL锁定批量更新

我将在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 
+0

显然,如果两个线程同时读取计数,然后继续更新,则行数可能会超过20.某些示例代码将有助于诊断确切的情况。 – Andomar

+0

我已经添加了我的代码,希望您可以帮助更多。我认为问题就像你说的,但有没有办法解决这个问题? 我认为ISOLATION LEVEL可能对此有所帮助。 – hhoud

+0

maxRunning = 0的自由通行证似乎很腥...... 50个线程可能会读取它,然后更新50行 – Andomar

回答

0

我已经能够通过对树的存储过程设置隔离级别序列化+交易这(两个我没提,因为我没有修复它认为他们对这个问题很重要)。显然它是多个存储过程相互干扰的组合。

如果你知道一个更好的解决方法,可以给我更好的表现,请让我知道!