【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。

猜你喜欢

转载自blog.csdn.net/qq_29234631/article/details/82465759
db2