2011-03-28 80 views
6

我目前正在SQL Server 2008數據庫上進行一些實驗。更具體地講,我有一個使用數百個併發線程的執行數千個任務JDBC應用程序,每個運行數據庫以下查詢:SQL Server 2008:發生死鎖...沒有任何鎖

UPDATE from Table A where rowID='123' 

但是,我得到一噸的死鎖錯誤的( SQL異常1205),只要我將隔離級別設置爲高於READ_UNCOMMITTED。即使我設置了行鎖定,表鎖定和排他鎖提示,它也會發生!即使在不使用鎖的快照隔離中,我仍然會遇到死鎖錯誤。

我通過SQL Profiler運行了一個跟蹤,以便在發生這種情況時獲取死鎖圖形,但它沒有多大用處。它顯示受害者進程連接到一個「線程池」,連接到數百個其他進程。您可以點擊此處查看:

http://i.stack.imgur.com/7rlv3.jpg

沒有人有任何線索,爲什麼發生這種情況?在過去的幾天裏,我一直在瘋狂地試圖找出答案。我目前的假設是,它與我的數據庫實例中可用的工作線程,可用內存量或與實際查詢級別鎖無關的事情有關。

謝謝!

+0

[看過這個了嗎?](http://blogs.msdn.com/b/bartd/archive/2008/09/24/today-s-annoyingly-unwieldy-term-intra-query-parallel-thread- deadlocks.aspx)你的更新語句是否有一個並行計劃? – 2011-03-28 21:32:43

+0

你是說''READ_UNCOMMITTED'生效時,這些死鎖**永遠不會發生?對我來說,這並不明顯,這將如何影響所顯示的'update'語句。 – 2011-03-28 21:41:08

+0

哇!在這麼短的時間內,我並不期待這種壓倒性的反應!在READ_UNCOMMITTED下仍然會發生死鎖,但是隻有當有很多很多併發線程正在進行時(大約爲1000),纔會發生死鎖。我對這種模糊性表示歉意。 – akwok 2011-03-28 23:27:02

回答

1

像這樣的死鎖/鎖是奇怪的,並指向SQL服務器以外的東西。值得的是,我們遇到了很多死鎖問題,結果是磁盤瓶頸!

我建議你運行perfmon(顯然在那之後有很多其他的工具),看看它是如何做的。

1

你不能做任何事情 SQL Server的無鎖 - 即使NOLOCK陳述貼滿將發佈在最低限度模式鎖和大概幾頁鎖最基本的查詢。

爲了解決死鎖問題,您需要獲取T1204死鎖跟蹤(有關更多詳細信息,請參閱Deadlock Troubleshooting, Part 1),其中將列出死鎖中涉及的確切鎖和對象 - 這應該有足夠的信息來解決頭部劃傷的數量)到底發生了什麼問題。

沒有完全瞭解死鎖背後的原因更改隔離級別,似乎一點點危險,我...

作爲一種預感這讓我想起一個問題,我有一個幾年前的 - 是UPDATE聲明死鎖針對SELECT聲明? (T1024跟蹤會告訴你這個)你有沒有非聚集索引rowID?如果是這樣,你可能想看看this MSDN article,特別是示例6:非聚簇索引。如果不是,那麼請繼續閱讀該文章,因爲它可能有助於解釋其他一些相關的死鎖情況,如果需要幫助分析它,還會發布T1024跟蹤結果。

6

你遇到了一個更深奧的野獸:資源死鎖。你有什麼線程比不能產生子任務(sys.dm_os_tasks)來執行它的工作,因爲所有的工人(sys.dm_os_workers)都很忙。反過來,忙碌的工作人員執行被受害者阻止的任務,可能在普通鎖上。

有兩個教訓我在這裏看到的帶回家:

1)您發佈的更新是試圖去平行。如果更新與您發佈的完全相同,則意味着唯一一件事:rowId上沒有索引。

2)您已在max worker threads設置的上限上反彈。難怪,考慮到您濫用客戶端中的線程(hundreds of concurrent threads to execute thousands of task),並且由於不必要的並行性而在服務器中將其倍增。

一個明智的設計將真正的異步連接(AsynchronousProcessing=true)上使用異步執行(BeginExecuteNonQuery),並使用未決請求池,因此不會去超過一定的閾值。更可能的情況是,您將通過table valued parameter傳入整批更新值,然後通過單個語句更新整批或多批的行。我知道我的所有鏈接都是針對.Net,而不是針對Java,我不在乎,你可以自己挖掘出相應的Java功能。

因此,雖然有趣的是,你發現了這樣一個深奧的僵局,它只會顯示出來,因爲你的設計,以及...糟透了。

+1

我會爲+1進行精彩的分析..但是用-1來鍛鍊,我們應該說,交貨嗎?省略2個字左右會讀取..更好? – RichardTheKiwi 2011-03-28 23:02:49

+1

感謝您的回覆,Remus。我明白這個設計太糟糕了,但它是有目的地完成的!我正在開發一個應該顯示以下內容的項目:1.)根據所選隔離級別的類型,存在不同的讀取異常,並顯示2.)經驗性性能命中選擇隔離級別,限制併發性而不是必要。無論如何,你的評論確實是有道理的,我會更多地研究它。至少你能夠爲我提供一個方向來進一步閱讀:-) – akwok 2011-03-28 23:29:47

+0

@akwok:我明白了。考慮到UPDATE必須首先找到要更新的行,然後更新它們。 'find'部分*受隔離級別的影響。即使REPEATABLE_READ也可以選擇以高粒度鎖定級別(頁面,表格)進行掃描。要考慮的第二件事是'更新'部分將與所有隔離級別下的另一更新(包括快照)發生衝突。此外,由於散列衝突,*不同*行的更新將會發生衝突:http://rusanu.com/2009/05/29/lockres-collision-probability-magic-marker-16777215/ – 2011-03-28 23:59:35