標籤:blog http 使用 os io strong 檔案 資料
看了網上很多關於死結的的部落格,大家通常介紹死結的原理,本人也寫一個詳細的分析。當然,是關於SQLSERVER的死結。
使用SQL Profiler抓取死結事件
2、選擇選項卡:事件選擇,勾選右下角的顯示所有事件,找到Locks事件,勾選上Deadlock graph。
3、再選擇第三個選項卡:事件提取設定,勾上死結XML,彈出檔案儲存路徑,輸入檔案名稱即可。
4、以上設定,出現死結時會儲存到死結XML檔案中,經操作發現只儲存了最後一個死結圖,如果死結比較多,需要使用SQL Profiler逐個儲存。
5、死結XML檔案預設尾碼為.xdl,雙擊直接開啟就會使用SSMS開啟,僅僅只能看到很基礎的資訊。如下:
這種圖示並不能詳細的說明問題。我們可以採取另外一種辦法,左鍵選擇死結XML檔案,右鍵選擇開啟檔案:文字編輯器。整個死結的內容就一目瞭然了,如下:
紅色的框框,是我標註出來的,我主要對黑色框框裡面的做詳細說明,其實有很多瞭解死結的朋友看了之後基本已經明白了。
1、 每一個死結XML檔案有一個根節點:deadlock-list。
2、 在根節點下,有一個節點deadlock victim="process59bcbc8",其中victim值為死結的編號,如果開啟的一個SQL Profiler下出現多個死結,那麼它們的編號是一致的,只有不同的SQL Profiler追蹤的死結編號才會有不同。此外該值為犧牲的進程ID號,與別的ID號區分,這個在之後會詳細介紹。
3、 在deadlock victim節點下有兩個節點,process-list,resource-list。process-list節點主要解釋死結的一些相關資訊。resource-list節點解釋鎖的授予情況。
4、 process-list節點,一般有兩個process節點,每個節點代表著一個死結中的一個進程,如果多個進程造成的死結,那就會出現多個process節點。我們先看第一個process節點,這個節點根據之前的圖片可以看出,是被犧牲的進程。
1)屬性id="process7a9a988",這個是被犧牲的進程ID號,在檔案中我們可以看到兩個process節點的ID號不同。另一個節點的id屬性為id="process7abee08"
2) 屬性waitresource=”PAGE: 7:1:8459005”,Page代表這是一個頁鎖,這個頁面出現在資料庫ID=7,檔案ID=1,頁面ID=8459005的位置。另一個Procee節點下的waitresource="PAGE: 7:1:7861369"。
3) 屬性transactionname ="SELECT",表示事務類型,SELECT表示這是一個查詢事務,可以跟另一個Procee節點下的transactionname屬性進行比較,transactionname="UPDATE"
4) 屬性lockMode="S",鎖的模式為共用鎖定。另一個process節點的鎖模式lockMode="IX"為意向獨佔鎖定。
5) 屬性status="suspended",鎖的狀態。另一個process節點的status="suspended"。
6) 屬性hostname="999VISTA"指操作這個事務的電腦名。另一個process節點的hostname="jack"
7) 屬性loginname="sa"指登入資料庫的SQL賬戶。另一個process節點的loginname="aaa"。
8) 屬性isolationlevel="read committed (2)"指交易隔離等級。
9) 節點executionStack,在它之下有兩個frame節點,第一個節點中間的文本是執行語句。第二個節點,沒弄明白什麼意思。
10) 節點inputbuf,這個節點中間的文本也是執行語句,與executionStack節點下第一個frame節點的文本相同,推測executionStack節點下第二個節點是不是在一個執行進程中其他的SQL語句??
5、 resource-list節點。這個節點下有兩個pagelock節點,分別代表兩個進程各自持有的頁鎖。如果有多個頁鎖,是不是會有多個pagelock節點?或者是表鎖那會是什麼節點??
1) 第一個pagelock節點,fileid="1" pageid="8459005" dbid="7",這個跟process-list節點下第一個process節點的屬性waitresource=”PAGE: 7:1:8459005”意思相同。objectname=” 表名",這個是表名,具體格式:db_name.schema_name.Table_name。
2) pagelock節點下有多個owner-list節點,這個是每一個進程就有一個節點,該樣本中由於死結是由兩個進程造成,只有兩個節點。
3) owner-list節點有一個owner,這個代表著鎖的授予情況,推測:如果持有多個鎖,可能有多個節點。
4) owner節點:id="process7abee08" mode="IX",id表示進程ID,mode表示鎖類型。
5) pagelock節點下有多個waiter-list節點,這個節點是與owner-list節點一一對應。
6) waiter-list節點有一個waiter節點,這個代表著鎖的授予情況,推測:如果持有多個鎖,可能有多個節點。
7) waiter節點:id="process7a9a988" mode="S" requestType="wait",id表示進程ID,mode表示鎖類型,requestType表示等待授予中。
8) 通過以上的介紹,我們可以瞭解到:
進程process7a9a988先擁有了Page:7:1:7861369的共用鎖定S,這個時候,它請求擷取Page:7:1:8459005的共用鎖定S,與此同時,process7abee08先擁有了Page:7:1:8459005的意向獨佔鎖定IX,又請求擷取Page:7:1:7861369的意向獨佔鎖定,這樣,兩個進程相互阻塞造成了死結的原因。我對此結合資料庫表結構分析,發現該表的每列欄位都有6880個字元,也就是說,一行就佔用了一個頁面,同時,進程process7a9a988使用的是LINQ查詢,由於LINQ導致這個查詢居然不走叢集索引,先走AccountID欄位的索引然後在嵌套迴圈主鍵索引CaseID,是死結的原因之一。
以上就是本人對死結的見解,如有異議,歡迎提出討論。