2010-11-03 40 views
0

我遇到以下(簡化)代碼的間歇性死鎖情況。ADO.NET DeadLock

DataSet my_dataset = new DataSet() 
SqlCommand sql_command = new SqlCommand(); 

sql_command.Connection = <valid connection> 
sql_command.CommandType = CommandType.Text; 
sql_command.CommandText = 'SELECT * FROM MyView ORDER BY 1' 

SqlDataAdapter data_adapter = new SqlDataAdapter(sql_command); 

sql_command.Connection.Open(); 

data_adapter.Fill(my_dataset); 

sql_command.Connection.Close(); 

我得到的錯誤是:

事務(進程ID 269)是 死鎖的鎖資源與 另一個進程,並已被選作 死鎖犧牲品。重新運行 交易。

據我所知,只需通過ADO.Net .Fill()命令填充數據集不應在數據庫上創建鎖定。 而且,它將從錯誤消息中看出該鎖由另一個進程擁有。 我查詢的視圖僅具有選擇語句,但它確實將幾個表連接在一起。

  • 只能進入select語句的視圖是否會受鎖定記錄的影響?
  • Can/Does ADO.Net .Fill()鎖定記錄?
  • 假設我需要填充一個DataSet,有沒有辦法避免潛在的數據鎖?

的SQL Server 2005(9.0.4035)

回答

2

帶連接的選擇查詢確實會導致死鎖。處理這個問題的一種方法是使用快照隔離在SqlTransaction中執行查詢。

using(SqlTransaction sqlTran = connection.BeginTransaction(IsolationLevel.Snapshot)) 
{ 
    // Query goes here. 
} 

可能會發生死鎖,因爲它會在執行連接之前鎖定要連接的每個表。如果另一個查詢在另一個查詢需要鎖定的表上有鎖定,反之亦然,則存在死鎖。用Snapshot Isolation剛剛從表中讀取的查詢不會鎖定它們。因爲讀取實際上是在交易開始時從數據的快照完成的,所以維持了完整性。

但是,這可能會對性能產生負面影響,因爲必須生成快照。根據應用程序的不同,最好不要使用快照隔離,相反,如果查詢失敗,會導致死鎖,請稍等片刻,然後重試。

嘗試找出死鎖發生的原因並更改數據庫結構和/或修改應用程序以防止死鎖也許會更好。這article有更多的信息。

+0

您能否擴展這方面的信息?我會非常感興趣的任何解釋性文件或鏈接,以及這種行爲如何以及爲什麼會通過。 – 0xCAFEBABE 2010-11-04 10:55:51

+0

@TME。我添加了更多信息。 – YWE 2010-11-04 14:17:57

+0

ADO「Classic」具有不同的鎖定級別......我想知道現在,ADO.NET的默認鎖定級別是什麼?上面的方法是如何去「調整」連接本身?如果將IsolationLevel設置爲Snapshot或ReadUncommited,是否還有讀鎖定? – 2010-11-04 14:31:55

0

這可能是遙遠而不是解決你的問題,首先要檢查其他的解決方案 - 但是,我們也有類似的問題(一個選擇鎖定記錄! )經過很多努力,我們追蹤到了文件/ SMB層。看起來在負載很重的情況下,從網絡驅動器(SAN)讀取文件被阻止,在實際的數據庫文件上創建一個等待讀鎖。這表示爲對所含記錄的鎖定。

但是,這是一個競爭條件,沒有驅動器上的負載無法重現。哦,它也是SQL Server 2005。

您應該能夠確定使用SQL Server包含的工具哪些事務處於彼此死鎖狀態。

1

你可以試試這個:

  • 下該查詢(例如,IsolationLevel.ReadUncommited)交易水平。
  • 在您查詢時使用NOLOCK提示。