1. 程式人生 > >【DB2】如何精確定位到死鎖

【DB2】如何精確定位到死鎖

本次差旅發現過很多死鎖,有很多死鎖定位方式。但是能精確定位的還是比較少。通過本次差旅實踐,發現通過dbpd來捕捉是最好的,也是最精確的。方法我總結如下:

1) 啟用死鎖監控

db2pdcfg –catch deadlock

當死鎖觸發時,會自動執行db2cos指令碼(在%db2dump%/bin 目錄下)。這個腳本里呼叫了db2pd來將當前資訊捕捉下來,其中主要捕捉的資訊包含如下:

Db2pd共捕捉了locks(鎖)、transaction(事務)、agents(代理程序)、application(應用)、dynamic(動態sql,這個最重要,是用於定位到sql)

2) 坐等死鎖。當死鎖觸發時,將自動生成 db2cos.process_id_application_id.txt,該檔案在db2的診斷目錄下(可以通過 db2 get dbm cfg | grep “DIA”來獲取診斷目錄位置)

3) 分析db2cos檔案:

a) 首先看-locks showlocks 模組,截圖如下:

找到其中包含【Sts】為W*,並且根據【ReleaseFlg】定位到相同slot的,總共會有兩處,一處狀態為 W*(是死鎖)、一處是 G(代表鎖擁有)。Slot相同,就代表他們是在同一個資料物件上等待。尋找後的資料,如下截圖:

從上圖,可以看出如下資訊:

Ø 在tabled=514和tabspacesId=4上等待(可以在syscat.tables 檢視上根據資訊定位到表名稱 select TABNAME , TABSCHEMA from syscat.tables where TABLEID=514 and TBSPACEID=4)

Ø 佔據表鎖的transactionHandle Id 為 28,是X排他鎖

Ø 等待表鎖的transactionHandle Id為55,是NS(下一鍵共享鎖)

有了這兩個Id接著往下走。我們已經知道了誰在等待、誰在佔有。

b) 檢視-transaction,獲取transaction id對應的agent id

可以看到Apphandle對應值應有了,下面就需要根據這個Apphandle去找sql執行的資訊,已經離目標不遠了哈。

c) 檢視-dynamic 資訊

觀察如下列【C-AnchID】、【C-StmtUID】、【L-AnchID】、【L-StmtUID】

其中C-AnchID是代表當前正在執行的sql槽號,L-AnchID是代表上次執行的sql槽號。OK,我們就需要通過這個槽號來找到對應的Sql。定位到如下模組:

然後根據【C-AnchID】、【C-StmtUID】、【L-AnchID】、【L-StmtUID】列值找到對應sql(AnchID->C- AnchID,StmtUID-> C-StmtUID),如下:

自此,我們發現了導致死鎖的Sql:

哪個sql 在等待鎖?

狀態為W*:

SELECT COUNT ( * )

FROM BIZ.WF_TASK A

   INNER JOIN

      BIZ.REI_FORM B

   ON A.RECEIPT_NO = B.REI_FORM_ID

WHERE A.TASK_STATUS = ?

AND A.HANDLE_ID = ?

AND A.RECEIPT_TYPE = ?

AND B.APPROVE_STATUS = ?

AND B.REI_FORM_NO = ?

哪個Sql在佔有鎖?

狀態為G:

UPDATE BIZ.REI_FORM

SET APPROVE_STATUS = ?

WHERE REI_FORM_ID = ?

整個過程截圖如下:

定位到Sql之後,我們就可以按照第三節中敘述的方法,該建索引就建立索引,sql寫的不規範就調整sql。