0

나는 무슨 일이 일어나고 있는지 또는 이상한 일이 무엇인지 완전히 이해하지 못한다고 생각합니다.SQL/코드 블로킹 읽기의 스냅 샷 격리

큰 그림 (. 첫 번째 경우는 것 같아요 가능성이 높습니다) :

  • 나는 그들이 시간이 소요될 수 있습니다로 비동기 적으로 특정 작업을 수행 할 수있는 웹 서비스를하기 위해 노력하고있어 나는하지 않습니다 클라이언트가 작업이 끝날 때까지 기다려야한다. (결과를 매번 쿼리하면 작업이 완료되었음을 알 수있다.)
  • 비동기 코드가 트랜잭션에 래핑됩니다. 문제가 발생하면 변경 사항을 롤백 할 수 있어야합니다.
  • 불행히도 비동기 코드의 마지막 단계는 동일한 데이터베이스를 쿼리하는 DIFFERENT 서비스를 호출하는 것입니다.
  • Snapshot 트랜잭션에서 모든 것을 래핑 했음에도 불구하고 서비스가 데이터베이스에서 읽을 수 없으므로 마지막 단계가 실패합니다.
  • 비동기 작업이 진행되는 동안 데이터베이스에서 간단한 SELECT 문도 수행 할 수 없습니다.

     using (var transaction = new System.Transactions.TransactionScope(System.Transactions.TransactionScopeOption.RequiresNew, new System.Transactions.TransactionOptions() { IsolationLevel = System.Transactions.IsolationLevel.Snapshot })) 
         { 
          var db = new DataModelContainer(); 
          Log test = new Log(); 
          test.Message = "TEST"; 
          test.Date = DateTime.UtcNow; 
          test.Details = "asd"; 
          test.Type = "test"; 
          test.StackTrace = "asd"; 
          db.LogSet.Add(test); 
          db.SaveChanges(); 
          using (var suppressed = new System.Transactions.TransactionScope(System.Transactions.TransactionScopeOption.Suppress)) 
          { 
           var newDb = new DataModelContainer(); 
           var log = newDb.LogSet.ToArray(); //deadlock here... WHY? 
          } 
          test = db.LogSet.Where(l => l.Message == "TEST").Single(); 
          db.LogSet.Remove(test); 
          db.SaveChanges(); 
          transaction.Complete(); 
         } 
    

    코드는 데이터베이스에 간단한 로그 항목을 (작성 : 여기

(5 모델 첫 번째 엔티티 프레임 워크를 사용하여) 나는 현재 트랜잭션을 테스트하기 위해 사용하고 코드의 샘플입니다 그래, 나는 그 순간에 놀고있어 그래서 값은 쓰레기 다.) 스냅 숏 격리를 허용하도록 SQL 데이터베이스를 설정 했으므로 지식은 여전히 ​​허용되어야합니다 (이러한 코드는 억제 된 새 트랜잭션과 새로운 DataModelContainer을 사용하여이 코드에서 테스트됩니다). 그러나 표시되지 않은 트랜잭션 또는 SQL Management Studio에서 LogSet을 쿼리 할 수 ​​없습니다. 전체 테이블이 잠겨 있습니다.

그래서 ... 왜? 트랜잭션 범위가 이와 같이 정의되는 경우 트랜잭션이 잠기는 이유는 무엇입니까? 또한 다른 격리 수준 (예 : ReadUncommited)을 시도했지만 여전히 테이블을 쿼리 할 수 ​​없습니다.

누군가이 동작에 대한 설명을 제공해 주시겠습니까?

+0

은 스냅 숏 격리입니다 귀하의 DB에서 활성화? "트랜잭션에서 사용되기 전에 ALLOW_SNAPSHOT_ISOLATION ON 데이터베이스 옵션을 설정하여 스냅 샷 격리를 활성화해야합니다." – Moho

+0

@Moho 예, 그렇습니다. * 스냅 숏 격리가 가능하도록 SQL 데이터베이스를 설정했습니다. 어쨌든,'ReadUncommited'처럼 다른 격리 모드 ('Serializable'보다 덜 제한적입니다)를 사용할 때 문제가 지속되고 SQL 서버에서 스냅 샷 격리가 필요하지 않습니다! – Shaamaan

답변

1

SSMS에서 현재 분리 수준을 SNAPSHOT으로 설정하고 문제가 해결되었는지 확인하십시오. 이는 아마도 READ COMMITTED으로 설정되어 있으므로 보류중인 업데이트로 인해 여전히 차단됩니다.

업데이트 :

다음과 같은 옵션을 변경 (지속적으로 SNAPSHOT 현재 격리 수준을 설정 한 피)에 의해 DB 전체 버전 행에 액세스 할 수 READ COMMITTED을 허용 할 수 있습니다 :

ALTER DATABASE MyDatabase 
SET READ_COMMITTED_SNAPSHOT ON 
+0

C#의 격리 수준 설정이 전혀 사용되지 않는 것처럼 느껴집니다. 스냅 샷 격리는 잠금이 발생하지 않아야하는 극단적 인 예일 뿐이지 만 다른 격리 수준에서도 문제가 발생합니다. 업데이트 된 C# 코드를 확인하십시오 - SSMS를 사용하여이 시점에서 테스트를 수행 할 필요가 없습니다.또한'READ_COMMITTED_SNAPSHOT'을 설정하는 것은 부분적인 해결책입니다 - 명시된 바와 같이 트랜잭션 격리가 올바르게 설정되지 않은 이유는 설명하지 않습니다 (설정되어있는 경우). – Shaamaan

+0

다른 세션의 격리 수준은 솔루션에서 설명한대로 중요합니다. 'READ COMMITTED'에 설정되어 있다면 - 변경 사항을 적용 할 때까지 잠길 것입니다. 이것이'READ_COMMITTED_SNAPSHOT' 설정의 전체 목적입니다 -'SNAPSHOT' 커밋을 기다리는 동안 블로킹을 방지하기 위해서 – Moho

+0

아, 문제가 무엇인지 알 것 같습니다. 나는 트랜잭션을 명시 적으로 열어야한다는 인상하에있었습니다 (예를 들어 간단한 SELECT SSMS 쿼리를 수행 할 때). – Shaamaan