在SQL Server的兩個或多個任務中,如果某個任務鎖定了其他任務試圖鎖定的資源。會造成這些任務的永久阻塞,進而出現死鎖。
下圖為例:
l 事務T1獲得了行R1的共享鎖。
l 事務T2獲得了行R2的共享鎖。
l 然後事務T1請求行R2的排它鎖,但是T2完成并釋放其對R2的共享鎖之前被阻塞。
l T2請求行R1的排它鎖,但是事務T1完成并釋放其對R1持有的共享鎖之前被阻塞。
現在T2與T1互相等待,導緻了死鎖。一般情況下螢幕會自動檢測并解決這個問題。
死鎖不僅僅發生在鎖資源上面,還會發生在一下資源上:
l 鎖。例如頁、行、中繼資料和應用程式上的鎖。
l 工作線程。如果排隊等待線程的任務擁有阻塞所有其他工作線程的資源,也會導緻死鎖。
l 記憶體。當并發請求等待獲得記憶體,而目前的可用記憶體無法滿足其需要時,可能發生死鎖。
l 并行查詢執行的相關資源。當一個語句用到多個線程運作時,線程之間有可能發生死鎖。
預設5秒鐘搜尋SQL Server中的所有任務,檢測是否有死鎖。如果有,将選擇一個作為犧牲品,并傳回1205錯誤。一般是開銷最小的事務作為犧牲品。
阻塞:當一個事務請求一個被其他事務鎖定的資源上的鎖時,送出請求的事務會一直等待下去,知道該鎖被别人釋放,自己能申請到位置。
預設情況下除非設定了LOCK_TIMEOUT,否則事務會一直等待下去。
死鎖:兩個或多個程序之間的互相等待。但是由于SQL Server有資料庫引擎死鎖檢測方案,至少5秒鐘會消除一個現有的死鎖。對性能的影響往往沒有阻塞嚴重。
1、 跟蹤标志1204和跟蹤标志1222:
打開跟蹤的語句:
DBCC
TRACEON(1222,-1)
DBCC
TRACEON(1204,-1)
對于1222産生的結果解釋:
1、 死鎖犧牲的程序:第一句deadlockvictim=processXXXX,中的xxxx就是死鎖犧牲品。
2、 死鎖發生的程序資訊:第二部分的process-list
3、 發生死鎖的資源資訊:在結果的resource-list中
2、 死鎖圖形事件:
從sqlserver profiler中得到,一般結合1222跟蹤标志和sql trace。
首先從errorlog中尋找1222的輸出結果,根據輸出的時間在跟蹤裡找到相應的連接配接。然後分析原因。
盡管死鎖不能完全避免,但是可以把機會降到最低:
l 按同一順序通路對象。
l 避免事務中的使用者互動。
l 保持事務簡短并處于一個批進行中。
l 使用腳底的隔離級别。
l 調整語句的執行計劃,減少鎖的申請數目。
按同一順序通路對象:
如果所有并發事務按同一順序通路對象,則發生死鎖的可能性會降低。
避免事務中的使用者互動:
避免編寫包含使用者互動的事務,因為沒有使用者幹預的批處理的運作速度遠快于必須等待使用者響應時的查詢速度。
保持事務簡短并處于一個批進行中:
運作時間越長,等待時間就越長,造成死鎖的機會就越高。
使用腳底的隔離級别:
确定事務能否在低隔離級别上運作。盡可能使用較低的隔離級别。
調整語句的執行計劃,減少鎖的申請數目:
可以從執行計劃中找出哪些資源耗得比較多。此時鎖的數目也會相應增多。