正如先前的堆棧溢出問題(TransactionScope和連接池以及SqlConnection如何管理IsolationLevel?)所證明的那樣,事務隔離級別在與SQL Server和ADO.NET(以及System.Transactions和EF的池連接)之間泄漏,因為它們建立在ADO.NET)。這意味著在任何應用程序中都可能發生以下危險的事件序列:請求發生,需要顯式事務以確保數據一致性其他任何不使用顯式事務的請求都會出現,因為它僅在執行非關鍵讀取。現在,該請求將以可序列化的方式執行,從而可能導致危險的阻塞和死鎖問題:預防這種情況的最佳方法是什么?現在真的需要在任何地方使用顯式事務嗎?這是一個自包含的副本。您將看到第三個查詢將繼承第二個查詢的可序列化級別。class Program{ static void Main(string[] args) { RunTest(null); RunTest(IsolationLevel.Serializable); RunTest(null); Console.ReadKey(); } static void RunTest(IsolationLevel? isolationLevel) { using (var tran = isolationLevel == null ? null : new TransactionScope(0, new TransactionOptions() { IsolationLevel = isolationLevel.Value })) using (var conn = new SqlConnection("Data Source=(local); Integrated Security=true; Initial Catalog=master;")) { conn.Open(); var cmd = new SqlCommand(@"select case transaction_isolation_level WHEN 0 THEN 'Unspecified' WHEN 1 THEN 'ReadUncommitted' WHEN 2 THEN 'ReadCommitted' WHEN 3 THEN 'RepeatableRead' WHEN 4 THEN 'Serializable' WHEN 5 THEN 'Snapshot' end as lvl, @@SPID from sys.dm_exec_sessions where session_id = @@SPID", conn); using (var reader = cmd.ExecuteReader()) { while (reader.Read()) { Console.WriteLine("Isolation Level = " + reader.GetValue(0) + ", SPID = " + reader.GetValue(1)); } } if (tran != null) tran.Complete(); } }}輸出:Isolation Level = ReadCommitted, SPID = 51Isolation Level = Serializable, SPID = 51Isolation Level = Serializable, SPID = 51 //leaked!
SQL Server:池連接之間的隔離級別泄漏
大話西游666
2019-10-26 13:15:51