2014-10-16 78 views
0

使用SQL Server 2008 R2當同一個更新語句(使用不​​同參數)併發運行時,我遇到死鎖。這裏是死鎖圖形(抱歉無法張貼在這裏的圖像還):使用簡單更新語句SQl服務器死鎖

http://i.stack.imgur.com/E6JBK.png

這裏是實際的執行計劃:

http://i.stack.imgur.com/emm9i.png

更新是這樣的:

exec sp_executesql N'UPDATE mapping.IssuerAlternateName 
SET 
    UseCount = UseCount + 1, 
    MostRecentlyAppeared = GETDATE(), 
    MostRecentlyAppearedUnderlyingAssetName = @p1 
WHERE ID = @p0 
',N'@p0 int,@p1 nvarchar(4000)',@p0=1234,@p1=N'blah blah blah' 

如果我已經正確理解了事情,我們正在嘗試從相同索引讀取和寫入(PK_IssuerAlternateName_1)

有什麼辦法可以解決這個問題嗎?我想知道,如果向主鍵添加附加索引並使用WITH INDEX可能會通過停止讀取PK_IssuerAlternateName_1(抱歉在執行計劃屏幕截圖中截斷全名)來解決該問題。

或者是最好的選擇只是爲了生活並重試交易,這是當前在.NET客戶端處理錯誤的方式。重試肯定是成功的,但如果可能的話,避免死鎖是一件好事。

感謝

+0

你目前是否在交易中包裝這個?如果是這樣,你使用的隔離級別是什麼? – mallocation 2014-10-17 01:03:09

+0

使用LINQ2SQL調用context.ExecuteCommand()... – MT1 2014-10-17 05:57:07

回答

0

在類似這樣的情況,我已經使用了UPDLOCK提示讓數據庫知道我打算更新此行。這不是暗示UPDATE聲明。沒有鎖定提示,它將首先獲取「共享」鎖定,然後嘗試升級。但是,這會在某些情況下導致死鎖。

您需要在自己的TransactionScope中執行此操作,以確保一切正常。

var sql = @"UPDATE mapping.IssuerAlternateName with (UPDLOCK) 
SET 
    UseCount = UseCount + 1, 
    MostRecentlyAppeared = GETDATE(), 
    MostRecentlyAppearedUnderlyingAssetName = @p1 
WHERE ID = @p0"; 

var options = new TransactionOptions() 
{ 
    IsolationLevel = IsolationLevel.ReadCommitted // don't use Serializable! 
}; 

using (var scope = new TransactionScope(TransactionScopeOption.RequiresNew, options)) 
{ 
    using (var context = new YourDbContext()) 
    { 
     // execute your command here 
    } 
} 
+0

因此,如果獲取更新鎖定而不是共享鎖定,則下一個進程將只等待此語句在啓動之前完成?對不起,我不是DBA ... – MT1 2014-10-17 18:26:44

+0

是的。而且我也不是DBA。我在隊列環境中有類似的經歷。 – mallocation 2014-10-17 18:36:18