DB2一次死锁问题的分析过程

Posted shengqin105

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了DB2一次死锁问题的分析过程相关的知识,希望对你有一定的参考价值。

业务反馈应用在提交表单报以下SQL错误:

错误信息:操作失败:提交失败[4]SQLExecute: 40001

[IBM][CLI Driver][DB2/LINUXX8664] SQL0911N  The current transaction has been rolled back because of a deadlock or timeout.  Reason code

"2".  SQLSTATE=40001


错误时间:2022-04-24 18:42:01

根据错误代码,这是一个典型的死锁问题,之前问题发生时已经建立dllock event monitor进行数据收集,收集的死锁信息以表的形式进行保存。

以下是分析的过程。


1.定位死锁

在CONNHEADER_DEADLOCK_MON表中取得时间相近且与应用报错时间一致的应用连接信息。

AGENT_ID

APPL_ID

APPL_NAME

CLIENT_NNAME

CONN_TIME

SEQUENCE_NO

438

192.168.1.1.59272.220424104202

**

**

2022-04-24 18:42:01.518595

00001

7273

192.168.1.2.59777.220424104200

**

**

2022-04-24 18:41:59.817282

00004

使用表的方式建立DB2死锁监视器及表定义参考以下官网链接:

​https://www.ibm.com/docs/en/db2/11.1?topic=monitoring-data-generated-by-deadlock-event-monitors​

​https://www.ibm.com/docs/en/db2/11.1?topic=monitors-information-written-tables-deadlock-event-monitor​


2.查询死锁信息

根据DEADLOCK_DEADLOCK_MON上的信息。

DEADLOCK_ID

DL_CONNS

EVMON_ACTIVATES

ROLLED_BACK_AGENT_ID

ROLLED_BACK_APPL_ID

ROLLED_BACK_PARTICIPANT_NO

ROLLED_BACK_SEQUENCE_NO

START_TIME

402

2

1

438

192.168.1.1.59272.220424104202

2

00001

2022-04-24 18:42:04.264236

显示:

  • (1)死锁的ID=402;
  • (2)死锁发生的时间是18:42:04.264236
  • (3)发生死锁时,随机回滚的是agent_id=438的dsp的应用;


3.查询死锁关联的AGENT

根据DLCONN_DEADLOCK_MON,查询DEADLOCK_ID=402涉及的应用,信息如下:

AGENT_ID

APPL_ID

APPL_ID_HOLDING_LK

DEADLOCK_ID

LOCK_MODE

LOCK_MODE_REQUESTED

LOCK_OBJECT_NAME

LOCK_OBJECT_TYPE

START_TIME

TABLE_NAME

TABLE_SCHEMA

STMT_TEXT

438

192.168.1.1.59272.220424104202

192.168.1.2.59777.220424104200

402

3

12

1

5

2022-04-24 18:42:04.290207

PT_PO_DT

KERNEL

(SQL1)

7273

192.168.1.2.59777.220424104200

192.168.1.1.59272.220424104202

402

5

3

13228376098

2

2022-04-24 18:42:04.290494

PT_PO

KERNEL

(SQL2)

上表数据是解析的重点,其意义分别是:

(1)应用(agent_id=438,DSP应用),需要对PT_PO_DT的对象(lock_object_name=1)申请NW锁(lock_mode_requested=12),但此对象已经被DCS应用(appl_id_holding_lk=192.168.1.2.59777.220424104200,即agent_id=7273)持有了S锁(lock_mode=3),锁的类型为表锁(lock_object_type=5);

(2)应用(agent_id=7273,DCS应用),需要对PT_PO的对象(lock_object_name=13228376098)申请S锁(lock_mode_requested=3),但此对象已经被DSP应用(appl_id_holding_lk=192.168.1.1.59272.220424104202,即agent_id=438)持有了X锁(lock_mode=5),锁的类型为行锁(lock_object_type=2);

agent_id = 438发生死锁时事务当时的SQL1,经查明作业的主要内容是对PT_PO、PT_PO_DT两个进行插入数据的作业;

agent_id = 7273发生死锁时事务当前的SQL2,经查明此事务的主要内容是对PT_PO、PT_PO_DT进行查询然后更新PT_PO的某几行的某字段。


4.定位锁的对象

依据LOCK_OBJECT_NAME查询DLLOCK_DEADLOCK_MON表的对象,如下(但没什么卵用):

DEADLOCK_ID

LOCK_MODE

LOCK_OBJECT_NAME

LOCK_OBJECT_TYPE

TABLE_FILE_ID

TABLE_NAME

402

5

13228376098

2(*row lock,SQL2)

534

PT_PO

402

3

1

5(*end of table lock, SQL1)

768

PT_PO_DT


5.死锁过程还原

由SQL反查业务的逻辑,结合上述的分析,死锁的对象关系梳理如下:

【DB2】一次死锁问题的分析过程_deadlock

(1)SQL1需要向两个表插入数据,先插入PT_PO,后插入PT_PO_DT,所以持有X锁申请NW锁,但都是行锁;

(2)SQL2先查后更新,由于SQL使用索引不当,查询进会对整表申请S锁,锁的对象与SQL1冲突,从而导致死锁的产生;

(3)S锁与X锁不兼容,S锁与NW锁也不兼容,故造成相互锁死,DB2随机踢掉了SQL1的事务,并报错;

(3)所以解决此问题的方向是,优化SQL2的语句,确保查询、更新时合理使用索引并精确定位至具体的row,可以避免发生此问题。

-------------------------

上述监控表中的元素均以数字表示相关锁的类型,比较费解,附上相关的数据字典用于辅助理解。(调整表格很麻烦,我直接贴图好了)


附表:LOCK_MODE元素

【DB2】一次死锁问题的分析过程_死锁_02

来自 <https://www.ibm.com/docs/en/db2/11.1?topic=reference-l#r0001286>

附表:锁的兼容关系(Lock Type Compatibility


【DB2】一次死锁问题的分析过程_死锁_03

来自 <https://www.ibm.com/docs/en/db2/9.7?topic=management-lock-type-compatibility>


附表:LOCK_OBJECT_TYPE

(取直sqlmon.h文件)

/******************************************************************************/
/* lock object type (lock_object_type) */
/******************************************************************************/

#define SQLM_TABLE_LOCK 1 /* table lock type */
#define SQLM_ROW_LOCK 2 /* table row lock type */
#define SQLM_INTERNAL_LOCK 3 /* Internal lock type */
#define SQLM_TABLESPACE_LOCK 4 /* Tablespace lock type */
#define SQLM_EOT_LOCK 5 /* end of table lock */
#define SQLM_KEYVALUE_LOCK 6 /* key value lock */
#define SQLM_SYSBOOT_LOCK 7 /* Internal lock on the sysboot table*/
#define SQLM_INTERNALP_LOCK 8 /* Internal Plan lock */
#define SQLM_INTERNALV_LOCK 9 /* Internal Variation lock */
#define SQLM_INTERNALS_LOCK 10 /* Internal Sequence lock */
#define SQLM_INTERNALJ_LOCK 11 /* Bufferpool lock */
#define SQLM_INTERNALL_LOCK 12 /* Internal Long/Lob lock */
#define SQLM_INTERNALC_LOCK 13 /* Internal Catalog Cache lock */
#define SQLM_INTERNALB_LOCK 14 /* Internal Online Backup lock */
#define SQLM_INTERNALO_LOCK 15 /* Internal Object Table lock */
#define SQLM_INTERNALT_LOCK 16 /* Internal Table Alter lock */
#define SQLM_INTERNALQ_LOCK 17 /* Internal DMS Sequence lock */
#define SQLM_INPLACE_REORG_LOCK 18 /* Inplace reorg lock */
#define SQLM_BLOCK_LOCK 19 /* Block lock type */
#define SQLM_TABLE_PART_LOCK 20 /* Table partition lock type */
#define SQLM_AUTORESIZE_LOCK 21 /* Autoresize lock type */
#define SQLM_AUTOSTORAGE_LOCK 22 /* Automatic storage lock type */
#define SQLM_XML_PATH_LOCK 23 /* XML Path lock type */
#define SQLM_INTERNALM_LOCK 24 /* Internal Extent Movement lock */
#define SQLM_GLOBAL_DDL_LOCK 25 /* Global DDL lock */


附表:锁的类型

(支持的表锁)

【DB2】一次死锁问题的分析过程_deadlock_04

(支持的行锁)

【DB2】一次死锁问题的分析过程_deadlock_05

以上是关于DB2一次死锁问题的分析过程的主要内容,如果未能解决你的问题,请参考以下文章

Mysql死锁如何排查:insert on duplicate死锁一次排查分析过程

db2 查杀死锁进程

DB2 锁问题分析与解释

MySQL一次死锁排查过程分析(双update)

记录一次 Mysql 死锁排查过程

mysql 发生死锁问题请求帮助