2017-09-15 93 views
0

當我使用創建事務的實體框架執行SQL查詢並鎖定某個表以在其上執行耗時的操作時,當另一個應用程序嘗試同時讀取同一個表時會發生什麼?SQL Server事務鎖

SQL Server是否會等待第一個事務完成並在鎖定消失時繼續執行,還是隻會返回一個表明該表無法訪問的錯誤?

+1

如果你想要一個在線排序的東西,你正在尋找'serializable'隔離級別。 [SQL Server隔離級別:A系列 - Paul White](https://sqlperformance.com/2014/07/t-sql-queries/isolation-levels)。注意,這並不一定會鎖定整個表,這取決於引擎將嘗試使用的鍵盤範圍鎖定的操作和索引。 [密鑰範圍鎖定 - MSDN](https://technet.microsoft.com/en-us/library/ms191272(v = sql.105).aspx) – SqlZim

+1

**默認情況下,SQL Server不會**行級別鎖定**,所以您幾乎不會鎖定整個表格。如果插入新行 - 是的,那些新行不能被另一個事務讀取,直到插入行的事務被提交**爲止 - 但這並不意味着整個表必須被鎖定才能允許插入(或更新或刪除)幾行! –

回答

1

是,實體框架是創建時自動SaveChanges被調用,默認的隔離級別爲Read Committed交易(實際上是從供應商獲取和SQL Server的默認提交讀)。

更多詳細信息可在this documentation page內找到。

爲了更改隔離級別,可以禁止EF的上下文在實例化上下文時使用它自己的事務(contextOwnsConnection: false)。

我的首選替代方案是使用TransactionScope,因爲它不需要對實例化上下文的方式進行任何更改,保存更改等。但是,請注意,its default isolation level is Serializable(引用的問題和答案也會告訴您如何更改它)

注意:建議不要長時間的事務處理,也許你應該看看using bulk operations(或檢查this library)以避免多次插入/更新/刪除由正常更改生成的保存。

-1

答案是,這取決於。 SQL可以通過多種方式鎖定數據。一般來說,如果您有DML操作(插入,更新,刪除)正在進行,並且您嘗試從該表中刪除select,它將阻止select,直到DML操作完成。

可以通過使用with (nolock)set transaction isolation level read uncommmitted覆蓋(在自己的危險)。做這些操作之一基本上允許你的查詢讀取「當前看起來像數據的任何數據」,這些數據可能不完整,甚至包含在交易完成時不會存在的行。

如果您的實際連接超時(這將在您的應用程序連接設置中出現)或者您在表格上導致了死鎖(一個更爲複雜的主題),那麼它返回錯誤的唯一時間。

1

默認情況下,EF將創建帶有READ COMMITTED SNAPSHOT的SQL Server數據庫。這意味着作家不會阻止讀者,讀者也不會阻止作者。有關基於行版本的隔離級別的詳細信息,請參閱Snapshot Isolation in SQL Server

雖然SaveChanges()將行鎖定在事務中,但試圖讀取這些行的其他會話將被重定向到版本存儲,並讀取這些行的最新已知版本。換句話說,讀者可以在任何正在進行的交易之前以一致的時間點查看每個表格。

如果您針對現有數據庫使用EF,則可能不會使用READ COMMITTED SNAPSHOT進行配置,在這種情況下,試圖讀取由事務鎖定的行的讀取器將阻塞,直到事務結束。通常這隻有幾毫秒,除非有大量事務正在運行,並且讀者正在嘗試掃描很多行,或者存在長時間運行的事務。在這種情況下,您應該努力將數據庫移到未來的READ COMMITTED SNAPSHOT。