2013-09-05 66 views
4

我有一個網站上有一個非常受歡迎的論壇,並且偶爾整天都會在同一個論壇上看到兩個相同(減去它們中的數據)更新語句之間發生的幾個死鎖。我不完全確定爲什麼會在此查詢中發生這種情況,因爲網站上有許多其他查詢以高併發性運行而沒有問題。兩個更新語句之間的SQL Server死鎖

Update Deadlock Graph

Full Image

查詢兩個進程之間的幾乎是相同的,該圖顯示了它作爲:

update [Forum] set [DateModified] = @DateModified, [LatestLocalThreadID] = @LatestLocalThreadID where ID = 310  

任何人都可以揭示這可能是導致此任何光線?

回答

2

這是因爲當您設置LatestLocalThreadID(以確保語句完成時行仍然存在)時,生成S鎖的ForumThreads外鍵。一個可能的修復方法是在更新語句前添加

SELECT * 
FROM ForumThreads WITH (XLOCK, ROWLOCK, HOLDLOCK) 
WHERE ID = @LatestLocalThreadID 

以便X鎖定。您也可以嘗試UPDLOCK作爲較不積極的模式。這當然會在其他地方造成死鎖,但這是最好的第一次嘗試。

1

通過訪問對象(表,頁面,行)始終以相同的順序阻止基本死鎖。在你的例子中,有一個進程首先訪問forum,第二個訪問forumThread,另一個線程訪問第二個進程,反之亦然。一個update通常首先搜索要更新的行並在搜索期間使用S鎖。已確定要更改的行由X鎖鎖定,然後發生實際更改。

快速和骯髒的解決方案可能會按照您需要的順序執行begin Tran然後lock對象,然後執行更新,然後commit再次釋放鎖。但是由於阻止鎖定,這會降低網站的總體吞吐量。

更好的方法是確定兩條語句(您可以編輯您的問題,並在找到它時給我們另一個)以及它們的執行計劃。應該有可能以某種方式重寫事務以按相同順序訪問所有對象 - 並防止死鎖。