2009-04-21 3 views
0

이 SQL (C#에서 호출 됨)은 때때로 교착 상태가됩니다. 서버에 부하가 많이 걸리지 않으므로 가능한 한 많이 잠그는 것이 사용됩니다.SqlServer, Transaction deadlock, 테이블이 실제로 잠겨있는 경우?

-- Lock to prevent race-conditions when multiple instances of an application calls this SQL: 
     BEGIN TRANSACTION 
-- Check that no one has inserted the rows in T1 before me, and that T2 is in a valid state (Test1 != null) 
      IF NOT EXISTS (SELECT TOP 1 1 FROM T1 WITH(HOLDLOCK, TABLOCKX) WHERE FKId IN {0}) AND 
      NOT EXISTS(SELECT TOP 1 1 FROM T2 WITH(HOLDLOCK, TABLOCKX) WHERE DbID IN {0} AND Test1 IS NOT NULL) 
      BEGIN 
-- Great! Im the first - go insert the row in T1 and update T2 accordingly. Finally write a log to T3 
       INSERT INTO T1(FKId, Status) 
       SELECT DbId, {1} FROM T2 WHERE DbId IN {0}; 

       UPDATE T2 SET LastChangedBy = {2}, LastChangedAt = GETDATE() WHERE DbId IN {0}; 

       INSERT INTO T3 (F1, FKId, F3) 
       SELECT {2}, DbId, GETDATE() FROM T2 WHERE DbId IN {0} ; 
      END; 

      -- Select status on the rows so the program can evaluate what just happened 
      SELECT FKId, Status FROM T1 WHERE FkId IN {0}; 

     COMMIT TRANSACTION 

저는 여러 테이블을 잠글 필요가 있다고 생각합니다.

테이블이 실제로 xlocked 될 때 - 처음 테이블을 사용할 때 - 또는 BEGIN TRANS에서 한 번에 모든 테이블을 잠글 때 약간 확신 할 수 없습니까?

답변

1

잠금은 잠금을 호출하거나 잠금으로 선택하고 커밋 또는 롤백시 해제됩니다.

다른 프로 시저가 T3에서 처음 잠기고 나중에 T1 또는 T2에서 잠기는 경우 데드락을 얻을 수 있습니다. 그런 다음 다른 트랜잭션이 필요로하는 것을 잠그는 동안 두 개의 트랜잭션이 서로를 기다리며 리소스를 확보합니다.

또한 테이블 잠금을 피하고 격리 수준을 직렬화 할 수 있습니다.

+0

+1은 직렬화 가능 모드를 언급합니다. 더 세분화 된 행 레벨 잠금은 데드락에 덜 민감합니다. –

+0

예, 테이블 잠금은 실제로는 성능이 현저히 나쁜 것은 사실이지만, 제대로 작동하게하는 유일한 솔루션이라면 솔루션입니다. –

0

잠금 기능의 문제점은 잠금 기능을 동시에 수행해야하는 모든 장소를 볼 필요가 있다는 것입니다. 문제를 여러 개의 작은 항목으로 분리하여 분리하여 개별적으로 살펴볼 방법이 없습니다.

예를 들어, 다른 코드가 동일한 테이블을 잠그고 있지만 분명하지 않고 잘못된 순서로 잠겨 있다면 어떻게 될까요? 그건 교착 상태를 일으킬거야.

교착 상태가 발견되어 현재 실행중인 다른 것을 알아 내려고 시도 할 때 서버 상태를 분석해야합니다. 그런 다음에 만 문제를 해결할 수 있습니다.

3

테이블 잠금을 사용하면 교착 상태가 발생할 가능성이 높아질 수 있습니다 ... 모든 교착 상태가 시퀀스 외 연산으로 인해 발생하는 것은 아닙니다 ... 일부는 (사용자가 발견 한대로) 전체 테이블을 잠그면 충돌이 발생할 확률이 높아집니다. 직렬화 가능 격리 수준을 사용하는 경우 범위 잠금은 다른 SQL 작업에 의한 삽입/삭제를 방지 할 수있는 인덱스 행에 배치됩니다. 이는 동일한 프로 시저의 두 가지 동시 작업에 의해 교착 상태가 발생할 수 있습니다. 동일한 순서로 작업을 수행합니다 ...

어떤 경우에도 교착 상태의 원인을 정확하게 찾으려면 SQL Server 추적 플래그 1204 및 1222를 설정하십시오. 그러면 SQL Server 로그에 세부 정보가 기록됩니다 교착 상태에 빠졌습니다.

Here이 작업 방법에 대한 좋은 기사입니다.

(끝나면이 플래그를 끄는 것을 잊지 마세요 ...)

+0

또한 SQL Server 2005의 경우 데드락을 기록하기 위해 프로파일 러를 사용할 수 있으며 예쁜 다이어그램을 그립니다. –

관련 문제