IBM®
跳转到主要内容
    中国 [选择]    使用条款
 
 
Select a scope: Search for:    
    首页    产品    服务与解决方案     支持与下载    个性化服务    
跳转到主要内容

developerWorks 中国  >  Information Management  >

DB2 for z/OS Web 应用程序数据库死锁分析

developerWorks
文档选项

未显示需要 JavaScript 的文档选项

讨论


级别: 初级

Zi Yan Tu (tuziyan@cn.ibm.com), Software Engineer, IBM
Li Shun Yang (yanglis@cn.ibm.com), Database Administrator, IBM

2006 年 11 月 06 日

本文阐述了开发人员和测试人员如何确定 DB2® for z/OS 环境下复杂 Web 应用程序中的死锁原因。

简介

在任何数据库环境中,死锁检测对于应用程序并发性都是很重要的。就像其他应用程序一样,在复杂 Web 环境中也需要能够确定任何死锁的起因。本文解释了如何配置 DB2 for os/390 的死锁跟踪设置,以启用死锁分析。先阐述了如何指定相关的 DB2 for z/OS 跟踪以获取足够信息,然后说明如何分析这些跟踪报告,并指出引起 DB2 for z/OS 环境中运行的复杂 Web 应用程序出现死锁的不良 SQL 语句。本文假定读者熟悉基本的 z/OS 操作。

使用 DB2 Performance Monitor 来配置跟踪

Locking 跟踪

若要启用 Locking 跟踪,首先打开 IBM DB2 Performance Monitor 应用程序。然后执行下面步骤:

  1. 配置 Collect Task A 以收集死锁跟踪。设置 Trigger by 4=Immediate Start 以立即激活任务。
  2. 选择 Locking, Data Type, IFICD, Requesting Location, Plan name and Authid,然后按 Enter

    图 1. 配置 Collect Task A
    配置 Collect Task A

  3. 选择数据类型 Lockout,然后按 Enter
  4. 在 IFCID Selection 面板中,选择下面的 IFICD,然后按 Enter
    105    DBID/OBID for database and tablespace translation  
    107    Data set open/close information                    
    172    Deadlock
    

  5. 在 Trace Qualification 面板中,填入 DB 用户名(在本例中为 TUSER03)和 DB 模式(在本例中为 TGUSER03),然后按 Enter

    图 2. Trace qualification 面板
    Trace qualification 面板

  6. 在 Trigger Immediately 面板中,填入 DB2 跟踪数据的输出数据集(例如,TGUSER03.DB2PM.TRACE01)。设置 Disposition 为 Overwrite
    注意:可以使用其他方法来配置 DB2 跟踪停止触发器(例如,经过一段时间后)。

    图 3. Trigger immediately 面板
    Trigger immediately 面板

  7. Enter,完成 Locking 跟踪配置。
  8. 如果 Web 应用程序运行期间有死锁,则激活 Collect Task A 来收集死锁信息。

SQL Activity 跟踪

按照下面步骤来配置 SQL Activity 跟踪:

  1. 配置 Collect Task B 以收集 SQL Activity 跟踪。设置 Trigger by 4=Immediate Start 来立即激活任务。
  2. 选择 SQL Activity, Data Type, IFCID, Requesting Location, Plan name and Authid,然后按 Enter
  3. 选择全部收集数据类型,然后按 Enter
  4. 在 IFCID Selection 面板中,选择下面的 IFCID,然后按 Enter
    16    Start of the first insert 
    20    Lock summary   
    53    Describe, SQL commit/rollback or error before SQL analyzed 
    58    End of SQL statement execution     
    59    Start of FETCH                   
    60    start of SELECT
    61    Start of INSERT, UPDATE or DELETE
    63    SQL statement to be parsed  
    64    start of PREPARE     
    65    start of OPEN CURSOR for static or dynamic SQL   
    66    Start of CLOSE CURSOR for static or dynamic SQL  
    68    Start of ROLLBACK                                
    69    End of ROLLBACK                                  
    70    Start of COMMIT phase 2                          
    71    End of COMMIT phase 2                            
    88    start of synchronous request (commit phase 1) 
    89    End of synchronous request (commit phase 1)   
    105    DBID/OBID for database and tablespace translation 
    

  5. 在 Trace Qualification 面板中,填入 DB 用户名(例如,TUSER03)和 DB 模式(例如,TGUSER03),然后按 Enter
  6. 在 Trigger Immediately 面板中,填入 DB2 跟踪数据的输出数据集(例如,TGUSER03.DB2PM.TRACE02)。设置 Disposition 为 Overwrite

    注意:可以使用其他方法来配置 DB2 跟踪停止触发器(例如,经过一段时间后)。

  7. Enter 完成 SQL Activity 配置。
  8. 在 Web 应用程序运行期间,激活 Collect Task B 来收集 SQL 语句。

分析跟踪报告以确定不良 SQL 语句

Web 应用程序中 DB2 锁的原理

通常 Web 应用程序有页锁和行锁。根据创建数据库所使用的数据定义语言 (DDL) 模式文件,可以确定正在使用的锁类型。行锁有三种模式:S(Share)、U(Update) 和 X(Exclusive)。要尽量避免的锁影响是挂起、超时和死锁。

当两个或两个以上应用程序进程均持有对资源(该资源是其他进程所需,且没有该资源时进程无法继续进行)的锁时,会发生死锁。 下面是关于发生死锁情况的详细解释:

  1. JobOne 和 JobTwo 是两个事务。JobOne 访问表 M,并持有页 B 的 X (exclusive) 锁,包含记录 000300。
  2. JobTwo 访问表 N,并持有页 A 的 X (exclusive) 锁,包含记录 000010。
  3. JobOne 请求表 N 页 A 的锁,同时仍持有表 M 页 B 的锁。因为 JobTwo 持有页 A 的 X 锁,所以作业被挂起。
  4. JobTwo 请求表 M 页 B 的锁,同时仍持有表 N 页 A 的锁。因为 JobOne 持有页 B 的 X 锁,所以作业被挂起。这种情况就是死锁。

为了改善应用程序的并发性,您需要找到引起死锁的 SQL 语句。然后,优化 SQL 语句以消除死锁。

根据死锁报告来分析锁信息

作为例子,我们假定当多个顾客同时登录并注册一个商店时发生死锁。您已经得到死锁跟踪报告和 SQL 语句报告。

首先,您应检查死锁跟踪报告(在本文中为 TGUSER03.DB2PM.LOCKS)。

下面是跟踪报告中一些关键参数的说明,有助于理解该进程:


图 4. 跟踪参数
跟踪参数

分析一下表 USERS(图 5 和图 6)上的第一个死锁。在图 5 中,可以看到死锁涉及到两个资源。分别是 row X'2B'、page X'00004E'、page USERS、DB SW03DB1 和 row X'2B'、page X'00004C'、table USERS、DB SW03DB1WAITERS =2 表明死锁中有两个等待者(0CC5440531190E26A4053107)。死锁发生在 12/05/05 06:30:09.40

从图 6 可以看到资源持有者和等待者与图 5 中的相反。等待者(实际上是图 5 中的持有者)正在请求持有者(实际上是图 5 中的等待者)所持有的资源。按照死锁的定义,在这种情况下会发生死锁。

现在,利用图 5 和图 6 来总结一下锁关系。

从图 5 中可以看到 LUW 0CC544053119 所持有的锁是 row X'2B'、page X'00004E'、table USERS、DB SW03DB1 上的行锁,且保持在 X 状态。等待者 LUW 实例 0E26A4053107 正在请求同一个资源上的 S 锁模式。而在图 6 中,LUW 0E26A4053107 所持有的锁是 row X'2B'、page X'00004C'、table USERS、DB SW03DB1 上的行锁,且保持在 X 状态。等待者 LUW 实例 0CC544053119 正在请求同一个资源上的 S 锁模式。因此发生死锁。

最后,请注意图 5 中的 BLOCKER is HOLDER --*VICTIM*,该线程 ("victim") 的作用是回滚以进行其他线程。


图 5. Locking 跟踪 —— 死锁报告
Locking 跟踪 —— 死锁报告


图 6. Locking 跟踪 —— 死锁报告
Locking 跟踪 —— 死锁报告

表 1 总结死锁分析:


表 1. 死锁分析
LUW 实例持有的资源(X 锁)请求的资源(S 锁)死锁时间表
0CC544053119SW03DB1.USERS.X'00004E'.X'2B'SW03DB1.USERS.X'00004C'.X'2B'06:30:09.41044991
0E26A4053107SW03DB1.USERS.X'00004C'.X'2B'SW03DB1.USERS.X'00004E'.X'2B'06:30:09.41044991

根据 SQL 活动报告来分析 SQL 信息

打印 SQL ACTIVITY 跟踪(在本文中为 TGUSER03.DB2PM.SQL),使用死锁所涉及的 LUW INSTANCE 数量(0CC544053119 和 0E26A4053107)进行过滤。可以发现最后一次 commit 操作应正好在死锁出现 (06:30:09.41044991) 前完成。接下来,搜索仅在完成最后一次 commit 操作后执行的 SQL 语句。

COMMIT processing in SQL ACTIVITY trace for INSTANCE 0CC544053119
COMMIT RECEIVED      06:28:50.72
COMMIT RECEIVED      06:28:50.85
COMMIT RECEIVED      06:28:50.97
COMMIT RECEIVED      06:28:51.04		the latest commit before the deadlock occurred.
|-------10--------20--------30--------40--------50--------60--------70--------80--------9|
|-------- XML error:  The previous line is longer than the max of 90 characters ---------|
COMMIT RECEIVED      06:30:09.61
COMMIT RECEIVED      06:30:09.64
COMMIT RECEIVED      06:30:09.73
COMMIT RECEIVED      06:30:09.77
COMMIT RECEIVED      06:30:09.80

因此,应该研究那些访问过 SW03DB1.USERS 且在 06:28:51.04 到 06:30:09.41044991 之间执行的 SQL 语句。如图 7 所示。


图 7. SQL 报告
SQL 报告

根据锁状态 X 和 S,对于资源 SW03DB1.USERS,在 SELECT 语句之前应是 INSERT 语句。

按照同样的方法,对于 INSTANCE 0E26A4053107,可以找到在出现死锁前进行最后一次 commit 的时间.

COMMIT processing in SQL ACTIVITY trace for INSTANCE 0E26A4053107
COMMIT RECEIVED     06:28:50.65		the latest commit before the deadlock occurred.
COMMIT RECEIVED     06:30:49.67

然后,研究那些访问过 SW03DB1.USERS 且在 06:28:50.65 到 06:30:09.41044991 之间执行的 SQL 语句。如图 8 所示。


图 8. SQL 报告
SQL 报告

从图 5 和图 6 中可以看到两个实例 0CC5440531190E26A4053107 正尝试提交 INSTER INTO USERSSELECT FROM USERS SQL 语句。由于 INSERTSELECT 语句之间没有 COMMIT,死锁可能是由表扫描引起的。因此运行并发线程时,出现了死锁。

结束语

本文阐述了如何使用 DB2 Performance Monitor 工具来收集死锁和 SQL Activity 跟踪。另外,给出了一个例子,演示如何通过分析跟踪找到一个死锁情况所涉及的 SQL 语句。使用该方法,开发人员和测试人员都可以发现不良 SQL 语句,并完成并发性能问题解决方案的第一步。



参考资料

学习

获得产品和技术
  • 使用 IBM 试用软件 构建您的下一个开发项目,这些软件可直接从 developerWorks 下载。

讨论


作者简介

Tu Zi Yan 是 China Software Development Lab(北京)的 System Test 小组的专职软件工程师。


Yang Li Shun 是 China Software Development Lab(北京)的 DB2 for z/OS 数据库管理员。




对本文的评价










回页首


IBM 公司保留在 developerWorks 网站上发表的内容的著作权。未经IBM公司或原始作者的书面明确许可,请勿转载。如果您希望转载,请通过 提交转载请求表单 联系我们的编辑团队。
    关于 IBM 隐私条约 联系 IBM 使用条款