2009-06-25 4 views
7

저는 ADO.NET 기반 웹 사이트를 구축하는 팀원입니다. 때로는 여러 개발자와 자동화 된 테스트 도구가 데이터베이스의 개발 복사본을 동시에 작업하는 경우가 있습니다.IsolationLevel.Snapshot을 사용하지만 DB가 여전히 잠겨 있습니다.

필자가 아는 한 최선의 방법은 잠금보다는 낙관적 인 동시성을 사용하는 스냅 샷 격리 수준을 사용하는 것입니다. 최선의 결과가 기대되며 영향을받는 행이 변경된 경우 트랜잭션을 커밋하려고하면 예외가 발생합니다. 거래하는 동안 다른 당사자가 , IsolationLevel 스냅 샷 우리는 또한 시도했다 READCOMMITTED 스냅 샷과 동일한 아니라고

Transaction = SqlConnection.BeginTransaction(IsolationLevel.Snapshot); 

참고 :

ALTER DATABASE <database name> 
SET ALLOW_SNAPSHOT_ISOLATION ON; 

및 C#으로 :

는 우리가 사용하는 스냅 숏 격리 수준을 사용하려면 현재 사용하고 있지는 않습니다.

개발자 중 한 명이 디버그 모드로 들어가서 .NET 응용 프로그램을 일시 중지하면 디버깅 중에 활성 트랜잭션과의 연결을 유지합니다. 이제는 이것이 문제가되지 않을 것으로 예상됩니다. 결국 모든 트랜잭션이 스냅 샷 격리 수준을 사용하므로 한 트랜잭션이 일시 중지 된 동안 일시 중지 된 트랜잭션에 잠금이 설정되지 않아 다른 트랜잭션이 정상적으로 진행될 수 있어야합니다. 물론 일시 중지 된 트랜잭션이 완료되면 충돌을 감지 할 가능성이 있습니다. 그러나 다른 개발자와 자동화 된 테스트가 방해받지 않고 진행될 수있는 한 허용됩니다.

그러나 실제로 한 사람이 디버깅하는 동안 트랜잭션을 중지하면 스냅 샷 격리 수준을 사용 했음에도 불구하고 동일한 행에 액세스하려고 시도하는 다른 모든 DB 사용자가 차단됩니다.

누가 이런 일이 발생하는지, 그리고/또는 어떻게 내가 진정한 낙관적 (비 차단) 동시성을 달성 할 수 있는지 알고 있습니까?

해상도 (나를 위해 불행한 것) : Remus Rusanu은 항상 다른 작가를 차단한다고 언급했습니다. 이것은 MSDN에 의해 뒷받침됩니다. - 확실히 나오지는 않지만 그렇게 말하지는 않겠지 만 독자와 작가의 자물쇠를 피하는 것에 대해서만 언급합니다. 요컨대, 내가 원하는 동작은 SQL Server에서 구현되지 않습니다.

답변

8

스냅 숏 격리 :이 ADO.NET의 트랜잭션 개체에 대한 클라이언트 측의 지시에 의해 또는 거래-SQL 쿼리 내에서 다음 문을 사용하여 중, 트랜잭션을 시작하기 전에 완료해야합니다 수준의 영향은 모든 격리 수준과 마찬가지로 읽기만 영향을줍니다. 글쓰기가 여전히 서로를 차단하고 있습니다. 표시되는 내용이 읽기 블록이라고 생각되면 추가 조사를 수행하여 차단이 발생하는 자원 유형과 자원 이름 (wait_type 및 wait_resource는 sys.dm_exec_requests)을 확인해야합니다.

개발자가 디버거를 몇 분 동안 쳐다 보면서 시나리오를 지원하기 위해 코드를 변경하는 것을 권장하지 않습니다. 이 시나리오가 프로덕션 환경에서 반복 될 수 있다고 생각되면 (즉, 클라이언트가 멈춤) 다른 이야기입니다. 원하는 것을 얻으려면 트랜잭션이 끝나기 전에 기록하기를 최소화하고 모든 기록을 수행해야합니다. 단 하나의 호출로 반환 전에 커밋합니다. 이 방법으로는 클라이언트가 오랫동안 X 잠금을 유지할 수 없습니다 (X 잠금을 유지하면서 잠글 수 없음). 실제로 이것은 매우 어렵고 개발자들이 데이터 액세스 코드를 작성하는 방법에 많은 훈련이 필요합니다.

+0

프로덕션 환경에서는이 동작이 발생하지 않습니다. 반면에 개발 버전은 매우 중요합니다. 개발을 원활하게 수행하려면 코드 변경을 기꺼이해야합니다. 안타깝게도 "svn-esque"스타일의 잠금 (최선의 노력을하고 단순히 충돌에 실패 할 수 있음)이 구현되지 않은 것 같습니다. 작은 트랜잭션을 모두 차단하지 않고 장기 실행 및 복잡한 트랜잭션을 수행하는 기능은 유용 할 수 있습니다. 즉, 차단을 피하기에 이상적인 트랜잭션을 적게 사용합니다. –

+1

은색 총알이 없습니다. 그러나 urself가 쓰기와 쓰기로 차단되는 경우가 종종 있는데 왜 이런 일이 발생하는지, 왜 다른 '요청'이 같은 데이터의 업데이트를 야기하는지 고려해야합니다. 아마도 응용 프로그램을 더 잘 분할하여 중복 가능성을 낮출 수 있습니다. 아마도 일부 업데이트는 지연 될 수 있고 사용자 트랜잭션 (enque/dequeue는 무료로 조심스럽게 처리 할 수 ​​있음) 중에 작업 테이블에 대기열에 포함 된 다음 나중에 전용 배치 프로세스에 의해 처리 될 수 있습니다. 또한 모든 트랜잭션이 필요한 최소 잠금 만 유지하는지 확인하십시오 (페이지/테이블 잠금 없음, 에스컬레이션 없음, 쓸데없는 테이블 스캔 없음). –

2

개발자가 거래를 일시 중지 한 경우 잠금을 보았습니까? 또한 스냅 샷 격리 수준을 켜기 만해도 많은 영향을 미치지 않습니다. ALLOW_SNAPSHOT_ISOLATION을 (를) 설정 했습니까? 데이터베이스 스냅 숏 격리, 개발자를위한 활성화 된 사용자가 그들의 트랜잭션이 스냅 샷 모드에서 실행하도록 요청해야합니다

ALTER DATABASE <databasename> 
SET READ_COMMITTED_SNAPSHOT ON; 
GO 

ALTER DATABASE <database name> 
SET ALLOW_SNAPSHOT_ISOLATION ON; 
GO 

후 :

은 다음 단계입니다.

SET TRANSACTION ISOLATION LEVEL SNAPSHOT 

주권

+0

데이터베이스에 allow_snapshot_isolation이 설정되어 있습니다. 그렇게하지 않으면 즉각적인 예외가 발생합니다. allow_snapshot_isolation이 해제되어 있으면 (즉 격리 수준 설정이 자동으로 실패하지 않는 경우) 격리 수준을 스냅 샷으로 설정할 수 없습니다. 정확한 명령을 반영하도록 게시물을 업데이트합니다. 감사합니다! –