記一次死結問題的排查

來源:互聯網
上載者:User

最近遇到了一個死結問題, 記錄一下排查的過程.

SQL Server中的死結是DBA們經常會遇到的問題. 

常有人混淆了死結和阻塞, 其實他們的區別還是很明顯的.
 阻塞的一般原因可能是進程在等待事務提交,或者某個操作的完成, 是資源上的衝突, 只要等待足夠長的時間,是一定可以解決的;  但是死結是邏輯上的衝突, 也就是說無論等待多長的時間, 更換多麼強大的硬體, 都是無法解決死結的.
在SQL 2005以後的版本中, 用profiler去跟蹤死結的方式, 是最方便的. 使用 deadlock graph事件進行跟蹤, 可以產生非常直觀的圖示, 將死結發生的原因直接呈現出來.

以下是最近碰到的一次死結, 可以看到有兩個進程,78和74,在頁496081和頁5102680上發生了死結.


接下來看一下進程74當時在執行什麼語句


可以看出, 進程74當時執行了一條update語句

update atm_status set status='C', date='20120220', time='122016' where atm_no='97793914'

所以這個死結問題就可以這樣解釋: 進程74在更新表時,在頁496081上獲得了獨佔鎖定,並且請求頁5102680的更新鎖定, 而進程78卻獲得了頁5102680的獨佔鎖定,而請求頁496081的更新鎖定, 這樣兩個進程互相等待對方所擁有的資源, 於是就發生了死結.

但是接下來在跟開發人員討論的中, 遇到了一個問題.  表atm_status明明中只有一條記錄被這條update語句更新了, 並且通過dbcc page看到頁496081上確實儲存著要更新的那條記錄,  那為什麼進程74要獲得另一個頁上的更新鎖定呢?

仔細琢磨了一會兒, 查看了一下表的結構, 找到了原因.

表atm_status上是沒有任何索引的, 所以在做update時, 是用表掃描的方式, 逐頁的得到要更新的記錄. 在update的過程中,進程會對錶中的每個頁都請求更新鎖定, 如果得到了更新鎖定並且要更新的資料在此頁內,就把更新鎖定變為獨佔鎖定,進行更新. 這樣處理完一頁後,再依次處理表中的下一頁. 由於一條語句就是一個事務, 所以之前在其他頁上獲得的獨佔鎖定會一直保持著到語句執行結束.  這也正是進程74雖然只更新一條記錄, 卻在持有獨佔鎖定的同時, 還要在另一個頁上請求更新鎖定的原因.

分析出了原因, 解決這個死結的問題就比較容易了. 只要在列atm_no上加上合適的索引, 用索引搜尋替代表掃描的方式去更新資料, 那麼進程就只在需要更新的那一個頁上申請更新鎖定就行了, 不會再發生這樣的死結.

由此可見, 因為缺少合適的索引而導致的低效率查詢, 是產生死結的可能原因之一. 






聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.