技术开发 频道

按照事务类型分析DB2 事物的性能

预处理语句事件

本步的任务是处理从上一节中得到的事件记录文件 eventmon.txt,将其中无关的事件过滤掉。一个事件记录文件往往会包含很多种事件,例如 SQL 语句事件、事务语句事件、数据库连接事件、死锁时间等。由于在本方法中只关心语句事件,因此需要将所有的非语句事件过滤掉。在事件记录文件中,每一个事件的第一行均为一个事件序号和事件名称:

  • Connection Header Event ...
  • Statement Event ...

SQL 语句和事务语句的事件名称均为“Statement Event…”,因此可以将名称不是“Statement Event…”的事件全部过滤掉,得到语句事件文件。

将事件按照事务分组

本步的任务是将属于同一事务的语句事件聚为一类,将原本无关的语句事件划分为一组事务的实例,每个事务实例中包含其执行的 SQL 语句和事务语句。


图 4. 事务分组
事务分组

由于数据库系统是支持并发访问的,即不同的应用程序可能同时进行数据库操作,因此捕获到的语句事件可能是多个事务交叉进行的。例如图 4 所示,SQL Event 1,SQL Event 2 和 Commit 1 是由一个应用程序执行的一个事务,而 SQL Event 3-6 和 Commit 2 是另一个应用程序执行的事务。 但是在输出的事件记录文件中,SQL Event 3 在 Commit 1 之前。因此不能简单的通过 Commit/Rollback 语句事件来作为区分事务的边界。

在 DB2 中,事件监测器的事件记录中有两个属性 Appl Id 和 Appl Seq number,这两个属性一起唯一地标识一个事务,每当事务结束(即 COMMIT 或 ROLLBACK 终止工作单元)时,Appl Seq number 就会递增。在本方法中就是通过这两个属性来划分事务的。通过程序或文本处理软件将上一节 中得到的语句事件文件按照 Appl Id 和 Appl Seq number 分类,将这两个值相同的作为一个事务。


清单 3. 事务实例文件

                
Transation Instance 1
    AppHandle = 138
    SqlNumber = 0001
    StartTime = 01/12/2007 17:41:14.773360
    EndTime = 01/12/2007 17:41:27.483101
    ExeTime = 12.709741  Second
    SQL 1 in Transation 1
        	SqlStatement = SELECT COUNT(*) FROM ACCOUNTEJB
        	Operation = Open
    		StartTime = 01/12/2007 17:41:14.773360
EndTime = 01/12/2007 17:41:14.993548
    		ExeTime = 0.220188 Second
Operation = Close
        		StartTime = 01/12/2007 17:41:14.995881
        		EndTime = 01/12/2007 17:41:15.086653
        		ExeTime = 0.090772 Second
waitTime = 0.002333 Second
SQL 2 in Transation 1
	SqlStatement = SELECT * FROM ACCOUNTEJB WHERE ACCOUNTID = ?
        	Operation = Open
    		StartTime = 01/12/2007 17:41:19.957377
       		EndTime = 01/12/2007 17:41:19.958135
        		ExeTime = 0.000758 Second
        		waitTime = 4.870724 Second
Operation = Close
StartTime = 01/12/2007 17:41:20.037864
EndTime = 01/12/2007 17:41:20.039575
ExeTime = 0.001711 Second
waitTime = 0.079729 Second
SQL 3 in Transation 1
	SqlStatement =
	Operation = Static Commit
Start Time: 01/12/2007 17:41:27.483077
  		Stop Time:  01/12/2007 17:41:27.483101
  		Exec Time:  0.000024 seconds
Transaction Instance 2
	…
		

将事务实例按照类型聚类

在上一节中已经生成了关于事务实例的执行信息报告,可以从中得到一个事务实例中各个SQL语句的执行时间以及语句之间的等待时间。但是在数据库操作中,往往会反复的执行同一个类型的事务。例如一个网上银行系统,登陆、转账等事务会被不同的应用程序不断的调用。这样就会出现一种现象,即一个数据库系统的事务实例报告中,有很多实例属于同一个事务类型。属于同一个类型的实例是由同一段应用程序代码执行的,但是参数值可能有所不同。如登陆事务,每次登陆的用户账号可能不一致。

为了统计同一类型的事务的性能,还需要将事务实例按照类型划分,然后计算其中的SQL语句的平均、最大最小时间。如何判断哪些事务实例属于同一类型是一个比较复杂的问题。由于在系统运行过程中一个事务类型的逻辑会发生变化,例如登陆事务可能会根据密码正确与否执行不同的SQL语句序列,所以很难全自动的将事务实例分类,最好引入一定的规则来作为判断的依据。常见的分类方法有:

  1. 自动匹配法。将执行的SQL语句逐一进行字符串匹配,每一个SQL语句都相同的事务实例被划分为同一类事务。这种方法的优点是简单, 缺点是可能把原本属于同一个类型的事务划分成两类。
  2. 将含有SQL语句的应用程序源代码作为划分依据。这样可以较为精确的匹配事务实例,并且由于源程序中包含了程序逻辑,即使一个 类型的事务有不同的逻辑也可以被匹配。
  3. 用户输入规则作为划分依据。例如,用户给出规则:将含有“select * from accountejb where accounted=?”语句的事务划分为一类。

按照如上方法划分之后,可以得到如表 2 所示的事务性能数据:


表 2. 事务类型性能报告
事务类型性能报告 

综合事务类型信息和应用程序状态,得到事务性能分析报告

在上一节中得到的事务性能数据已经比较详细的反映了一个数据库系统中的事务执行情况,包括该类型事务执行的次数,执行时间,其中每一个 SQL 语句的执行时间以及每两个 SQL 语句之间的等待时间。数据库管理员和开发者可以根据这些数据决定是否需要调优一个事务的性能,以及应该调整哪一个 SQL 语句。

针对某一个 SQL 语句,如果其执行时间比较长,往往有两种可能,一种是其在等待其他数据库操作释放锁,另一种是该 SQL 语句自身比较复杂,需要较多的 CPU 计算资源或 I/O 操作。为了区分是哪一种原因,需要将快照得到的应用程序状态和事务性能数据综合分析。

应用程序的快照中包含应用程序 ID 和快照时间戳。比较快照结果文件和事务实例文件中应用程序 ID 和发生时间相同的记录,可以得到该应用程序在执行一个 SQL 语句时的状态,是 UOW Executing 还是 Lock wait。将应用程序状态的统计信息加入事务性能报告,则可以帮助数据库管理员和开发者找到调优该 SQL 语句的方法。


表 3. 事务性能报告
事务性能报告 

总结

数据库的事务性能分析比 SQL 语句性能分析粒度大,比调整数据库参数影响的范围小。本文介绍的方法通过利用 DB2 的监测工具和对监测数据的分析,得到关于事务的性能报告,为数据库性能调优提供了更多的信息。在典型的 OLTP 系统中,一个前端的界面操作往往对应后端数据库的一个事务,因此提高事务的性能对于终端用户的体验有较为直接的改善。

0
相关文章