在今天的文章裏,我想談下SQL Server裏如何處理死鎖。當2個查詢彼此等待時會發生死鎖,沒有一個查詢能夠繼續它們的操做。首先我想給你大體講下SQL Server如何處理死鎖。最後我會展現下SQL Sever裏特定的死鎖類型,還有你如何避免和解決它們。sql
死鎖的好處是SQL Server自動檢測並解決它們。爲了解決死鎖,SQL Server須要回滾2個事務中最便宜的那個。在SQL Server上下文中,最便宜的事務是寫入事務日誌更少字節的那個。併發
SQL Server在後臺進程中實現死鎖檢測稱爲死鎖監控(Deadlock Monitor)。這個後臺進程每5秒鐘運行一次,爲死鎖檢查當前鎖定狀況。在最壞的狀況中,所以一個死鎖不該該超過5秒。這個查詢會回滾並收到1205錯誤號。死鎖的好事是你能夠完整從錯誤狀況下還原,不須要用戶的任何干預。一個聰明的開發者必須按下列步驟來從死鎖中恢復:spa
從新提交查詢後,這個查詢應該繼續執行,沒有任何問題,由於其它查詢已經完成它的事務。固然你應該保持再次發生死鎖的跟蹤,這樣的話,你不用反覆重試你的事務。線程
你能夠用多種方法來故障排除死鎖。SQL Server Profiler提供Deadlock Graph事件,一旦死鎖檢測到就會發生。若是你在SQL Server 2008或更高,你可使用故障排除來故障排除死鎖場景。擴展事件提供你system_health事件會話,它跟蹤自SQL Server上次重啓後發生過的死鎖。還有啓用1222跟蹤標記,SQL Server會把死鎖信息寫入錯誤日誌。設計
在SQL Server裏會發生各類類型的死鎖。在這一部分我想進一步談下最多見的幾個。日誌
幾乎每一個SQL Server我看到最典型的的死鎖是著名的書籤查找死鎖,當你有同時對彙集和非彙集索引讀寫活動時發生。它基本上是由於很差的索引設計形成的。在我做平常SQL Server的故障排除重,我能夠說全部的死鎖,至少有90%能夠經過更好的索引設計來解決。書籤查找死鎖能夠經過提供覆蓋非彙集索引輕鬆解決。server
另外一個常見的死鎖是所謂的循環死鎖(Cycle Deadlock),這裏你的每一個查詢用不一樣的順序訪問表。爲了不這個特定的死鎖,你要確保每一個查詢用一樣的順序訪問表。在SQL Server裏會發生的最有意思的死鎖是所謂的內部並行死鎖(Intra-Parallelism Deadlock),這裏平行的運算符在各自的線程內部死鎖。下圖展現了一個典型死鎖圖。blog
圖片自己就是一個藝術品,它因觸發SQL Server裏的BUG而發生。遺憾的是,這個BUG不會被微軟修正,由於它引入迴歸的可能性。所以你要確保引發這個死鎖的查詢,要在SQL Server裏單線程運行。你能夠經過多個選項來實現單線程執行:索引
另外一個死鎖的特效療法是啓用樂觀併發,尤爲是提交讀快照隔離(Read Committed Snapshot Isolation (RCSI)),他對你的程序是徹底透明的。使用樂觀併發,共享鎖消失,這意味着在SQL Server裏你能夠避免大量的典型鎖。進程
死鎖是SQL Server經過回滾最便宜的事務自動處理。然而你要儘量小的確保死鎖,由於每一個回滾的死鎖都會給你的終端用戶帶來很差的影響。死鎖能夠經過好的索引策略來避免,另外使用樂觀併發也是應付它們的特效藥。
感謝關注!
https://www.sqlpassion.at/archive/2017/02/20/how-to-handle-deadlocks-in-sql-server