2012-12-06 2 views
0

SQL Server 2008 R2 및 C#을 사용하고 있습니다.일괄 업데이트 용 SQL 잠금

상태 값이 인 값이 인 SQL Server에 일괄 처리 행을 삽입합니다. 그런 다음 얼마나 많은 행이 이미 상태가 R인지 확인하고 20 개 미만인 경우 행을 상태 으로 업데이트합니다. 삽입 및 업데이트하는 동안 항상 더 많은 행이 추가되고 업데이트됩니다.

여러 가지 방법으로 트랜잭션과 잠금을 시도했지만 여전히 : 새로운 배치가 활성화되는 순간에 수십 밀리 초 동안 R 상태의 행이 20 개 이상 있습니다. 몇 밀리 초가 지나면 20으로 안정화됩니다.

버스트가 작동하지 않는 이유는 누구입니까? 샘플 코드, 이유,이 주제에 대해 공유 할 수있는 것이 무엇이든 유용 할 수 있습니다! 감사합니다. 내가 didn를하기 때문에 내가 언급하지 않았다 (그 중 두 나무 저장 프로 시저에 격리 수준 직렬화 + 트랜잭션을 설정하여 문제를 해결할 수있었습니다

 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

: 다음

내 저장된 프로 시저입니다 그들이이 문제에 대해 중요하다고 생각하지 않는다). 분명히 서로 간섭하는 것은 여러 저장된 procs의 조합이었습니다.

나에게 더 나은 성능을 줄 수있는 더 나은 방법을 알고 있다면 알려 주시기 바랍니다.