0

我懷疑我不完全理解發生了什麼或發生了一些奇怪的事情。 (第一種情況的可能性更大,我猜。)SQL中的快照隔離/代碼阻塞讀取

大圖片:

  • 我想有一個Web服務執行某些操作異步,因爲他們可能會非常耗時,我不希望客戶端等待操作完成(只需查詢結果就可以看到操作完成)。
  • 異步代碼被封裝在一個事務中 - 萬一出現問題,我希望能夠回滾任何更改。
  • 不幸的是,異步代碼的最後一步是調用查詢同一數據庫的不同服務。
  • 儘管在Snapshot事務中包裝整個事件,但最後一步失敗,因爲該服務無法從數據庫中讀取。
  • 對於這個問題,雖然異步操作正在進行中,但我無法從數據庫執行簡單的SELECT語句。

這裏的(使用實體框架5模型第一),這我目前使用測試出交易代碼示例:

 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(); 
     } 

的代碼創建數據庫(一個簡單的日誌條目是的,我現在在玩耍,所以價值是垃圾)。我已經將SQL數據庫設置爲允許快照隔離,並且對於我的知識,仍應該允許讀取(這些正在使用新的抑制事務和新的DataModelContainer在此代碼中進行測試)。但是,我無法在被抑制的事務或SQL Management Studio中查詢LogSet - 整個表已被鎖定!

那麼...爲什麼?如果事務範圍被定義爲這樣,爲什麼它被鎖定?我也嘗試過其他隔離級別(如ReadUncommited),我仍然無法查詢表格。

是否有人可以提供這種行爲的解釋?

+0

是快照隔離在你的數據庫中啓用? 「快照隔離必須通過在事務中使用ALLOW_SNAPSHOT_ISOLATION ON數據庫選項之前啓用」 – Moho

+0

@Moho是的。 *我已將SQL數據庫設置爲允許快照隔離*。無論如何,當使用OTHER隔離模式時(比'Serializable'限制更少),問題依然存在,比如'ReadUncommited',並且這個甚至不需要在SQL服務器上啓用快照隔離! – Shaamaan

回答

1

在SSMS中,將當前的隔離級別設置爲SNAPSHOT,看看是否可以解決您的問題 - 它可能設置爲READ COMMITTED,並因此會因爲掛起的更新而阻塞。

更新:

您可以允許READ COMMITTED通過改變下列選項(和避免不必經常設置當前隔離級別設置爲SNAPSHOT)DB-範圍內訪問版本行:

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