2009-06-01 304 views
1

在生產SQL Server 2000數據庫中,我們遇到了一些非常煩人的死鎖情況。SQL Server 2000死鎖

主要設置如下:

  • SQL Server 2000企業版。
  • 服務器使用ATL OLE數據庫以C++編碼。
  • 通過存儲過程訪問所有數據庫對象。
  • 所有UPDATE/INSERT存儲過程都將其內部操作包裝在BEGIN TRANS ... COMMIT TRANS塊中。

我收集與SQL事件探查繼互聯網就像this one上幾篇文章了一些初步的痕跡(忽略它指的是SQL Server 2005和的工具,同樣的原則也適用)。 從跟蹤看來,它是兩個UPDATE查詢之間的死鎖。

我們已經採取可能從作爲發生降低問題的可能性了一些措施:

  • 選擇帶(NOLOCK)。我們更改了存儲過程中的所有SELECT查詢以使用WITH(NOLOCK)。我們理解具有髒讀取的含義,但被查詢的數據並不重要,因爲我們會進行大量自動刷新,並且在正常情況下,UI將具有正確的值。
  • READ UNCOMMITTED。我們已將服務器代碼上的事務隔離級別更改爲READ UNCOMMITED。
  • 交易範圍縮小。我們減少了交易的時間,以儘量減少發生數據庫死鎖的可能性。

我們也在質疑我們在大多數存儲過程(BEGIN TRANS ... COMMIT TRANS塊)內部有一個事務。在這種情況下,我猜測事務隔離級別是SERIALIZABLE,對嗎?那麼如果我們在調用存儲過程的源代碼中指定了事務隔離級別(如果我們也有),哪一個適用?

這是一個處理密集型應用程序,我們正在爲讀取(更大的百分比)和一些寫入命中數據庫。

如果這是一個SQL Server 2005數據庫,我可以用Geoff Dalgas answer on an deadlock issue concerning Stack Overflow,如果這甚至適用於我遇到的問題。但是,升級到SQL Server 2005目前還不是一個可行的選擇。我的問題是:你會怎麼走?您會採取哪些步驟來減少甚至避免發生死鎖,或者我應該使用哪些命令/工具來更好地揭示問題?

回答

0

在我的設置方案中死鎖的原因是在所有索引之後。我們正在使用(默認生成)non clustered索引表的主鍵。更改爲clustered索引解決了問題。

+0

它看起來像只是影響了一些時間,巧合得到了減少相同死鎖的機會。 – 2009-11-27 20:31:43

1

幾點意見:

  1. 在存儲過程中明確指定的隔離級別覆蓋主叫的isolatlation水平。

  2. 如果sp_getapplock可在2000年,我會使用它:

    http://sqlblogcasts.com/blogs/tonyrogerson/archive/2006/06/30/855.aspx

  3. 在許多情況下,序列化隔離級別增加你會得到一個僵局的機會。

  4. 2000年良好的資源:

    http://www.code-magazine.com/article.aspx?quickid=0309101&page=1

還有些巴特鄧肯的建議可能適用:

http://blogs.msdn.com/bartd/archive/2006/09/09/747119.aspx

0

除了Alex的答案:

  • 檢查代碼以查看是否按相同順序訪問表。我們最近做了這件事,並重新將代碼重新排序,以便繼續爲父母和孩子。系統已經發展壯大,代碼和功能更復雜,用戶更多:我們只是開始陷入僵局。

- 看看交易可以被縮短(如後,完成較早,處理少開始)

  • 確定你想不失敗,使用SET DEADLOCK優先級低,其中的代碼另一個 我們已經使用過了(SQL 2005在這裏有更多的選項),以確保某些代碼永遠不會死鎖並犧牲其他代碼。

  • 如果您在事務開始時有SELECT準備某些內容,請考慮HOLDLOCK(也許UPDLOCK)在此期間保持鎖定狀態。我們偶爾使用這個,所以不要在其他進程上寫入這個表。

0

我的猜測是,你正在經歷死鎖,或者:

  1. 因爲你的DML(更新可能)語句越來越上報到表鎖,或
  2. 不同的存儲過程訪問交易中的相同表格但順序不同。

爲了解決這個問題,我將首先檢查存儲過程,並確保修改語句具有他們需要的索引。

注意:這適用於目標表和源表(儘管NOLOCK,UPDATE的源表也會獲得鎖。請檢查用戶存儲過程中的掃描查詢計劃。與批處理或批量操作不同,大多數用戶查詢& DML在錶行的一小部分子集上工作,因此不應鎖定整個表。

然後,我會檢查存儲過程以確保存儲過程中的所有數據訪問都按照一致的順序完成(父 - >子通常是首選)。