2009-05-29 108 views
1

我有一個更新我的業務實體的例程。更新涉及大約6個不同的表格。所有的命令都在一個事務中執行。如何避免這些死鎖?

最近,我需要將一些代碼添加到從數據庫訪問查找表的例程中。查找代碼已經存在於另一個業務對象中,所以我使用了該業務對象。例如:

Using tr As DbTransaction = myConnection.BeginTransaction() 
    ExecuteCommand1(tr) 
    ExecuteCommand2(tr) 
    If myLookupTable.GetLookupTable().FindById(id).HasFlagSet Then 
     ExecuteCommand3(tr) 
    End If 
End Using 

但是,查找表業務對象掛起/死鎖。我認爲這是因爲它沒有引用原始程序正在使用的事務。

經過一番研究,我試圖把查找表邏輯放在自己的事務中,將IsolationLevel設置爲ReadUncommitted。這給了我想要的結果。但是,經過進一步的研究,如果我已經正確實施了這個方法,我現在會進行二次猜測。

假設我的查找表對象對活動事務的引用不可用,那麼我所描述的是否被認爲是最佳實踐?我覺得我可能會錯過一些東西。

+0

command1或command2是否在查找可執行文件? – 2009-05-29 00:18:46

回答

3

如果您在事務處理過程中正在進行讀操作,那麼您應該在事務上下文中執行該操作,而不是使用其他事務和髒讀操作。幸運的是,有一個簡單的解決方案:使用.Net TransactionScope對象而不是使用ADO.Net事務對象。 ADO.Net代碼非常明智,並且會徵用您在此事務中的所有操作,包括您的其他業務組件讀取。只要確保您的業務對象不會打開不同的連接,就會導致嘗試將現有事務升級爲分佈式事務,並將新連接加入其中。

另一種方法是在每次調用時傳遞SqlConnection/SqlTransaction對,但是在代碼中隨處傳播的可怕程度非常糟糕。

0

如果是我,我會重寫邏輯,所以我不必做一個未提交的閱讀。

0

避免死鎖的黃金法則是始終在每個事務中以相同的順序獲取表鎖。因此,看看其他事務中的代碼,看看他們使用表鎖的順序;那麼請確保您在交易中使用相同的訂單。

0

顯然,您的查找嘗試訪問專門被事務tr鎖定的行。如果您使用readuncommitted事務或在查找查詢中使用WITH(NOLOCK),您將看到所有未發生的可能正在發生的事務以及影響查找邏輯的更改。所以我不太確定這是多麼的可取。

我認爲最好找到一種方法來確保您的查找查詢參與當前事務,如果您需要在該事務中執行查找。如果所有這些操作都要在同一個線程中執行,那麼您可以做的一件事是在創建線程本地存儲時將事務對象存儲在線程本地存儲中,並使GetLookupTable方法爲線程本地存儲檢查事務對象,如果存在是一個事務集,您可以從該事務對象獲取連接。否則,您創建一個新的連接。通過這種方式,您的查詢將成爲該事務的一部分,並且應該運行其邏輯,而不會被當前事務阻塞,從而阻止當前事務,從而導致死鎖。