技术开发 频道

DB2事务日志使用经验

  B、 事务日志满场景一:当前未提交的事务太大,超过日志的限制。

  在会话1中执行:

  C:\Documents and Settings\administrator>db2 commit

  DB20000I SQL命令成功完成。

  提交前面未提交的事务。

  C:\Documents and Settings\administrator>db2 +c call proc_testlog(330000)

  SQL0964C 数据库的事务日志已满。 SQLSTATE=57011

  这时候我打开另外一个session,执行一个不相关的插入操作。

  C:\Documents and Settings\administrator>db2 "insert into test values(1112,1,’sdfsdfsdfsdf’,’sdfsdfsdfsdfsdf’,’sdfsdfsdffsdfsd’)

  DB21034E 该命令被当作 SQL 语句来处理,因为它是无效的“命令行处理器”命令。在

  SQL 处理期间,它返回:

  SQL0964C 数据库的事务日志已满。 SQLSTATE=57011

  可以看到,当日志满的时候其他的任何记日志的操作都将不能进行,所以整个系统基本处于不可用的状态,除非等事务回滚结束。

  OK,事务日志满的情况出现,现在我们就根据日志满的日志,来逆向分析是哪个操作导致的该问题,分析步骤如下:

  首先,确定哪个应用的事务占用了大量的日志空间:

  在回话2中执行: 

C:\Documents and Settings\administrator>db2pd -db sample -transactions

  
Database Partition 0 -- Database SAMPLE -- Active -- Up 0 days 00:02:27

  Transactions:

  Address AppHandl
[nod-index] TranHdl Locks State Tflag Tflag2

  Firstlsn Lastlsn LogSpace SpaceReserved TID

  AxRegCnt GXID

  …..

  
0x7FC21A80 7 [000-00007] 2 10 WRITE 0x00000000 0x00000

  
000 0x00003D86000C 0x000048C4FCD0 14014572 201955470 0x000000004F91

  
1 0

  …..

  可以看到上面红色部分, AppHandl为7的应用的一个事务占用了大量的日志。如果有多个应用占用了大量的日志,我们可以按照下面的方法逐个分析,看每个应用是执行了什么sql导致的占用如此大的日志。

  然后使用db2pd确定这个日志执行了什么语句导致占用了大量的日志: 

C:\Documents and Settings\administrator>db2pd -db sample -applications

  
Database Partition 0 -- Database SAMPLE -- Active -- Up 0 days 00:02:36

  Applications:

  Address AppHandl
[nod-index] NumAgents CoorEDUID Status C-

  AnchID C
-StmtUID L-AnchID L-StmtUID Appid

  WorkloadID WorkloadOccID

  …..

  
0x7AED8080 7 [000-00007] 1 1572 UOW-Waiting 0

  
0 185 1 *LOCAL.DB2.081111100729

  
1 1

  …..

  Application handle为7的应用,对应的L-AnchID为185,L-StmtUID为1。在回话2中继续使用db2pd找到对应的sql语句:

 db2pd -db sample -dynamic

  …..

  Dynamic SQL Statements:

  Address AnchID StmtUID NumEnv NumVar NumRef NumExe
Text

  
0x7EA7D540 185 1 1 1 1 1 CALL proc_testlog(?)

  …

  对应AnchID为185, StmtUID为1的语句,是CALL proc_testlog(?),通过上面的分析,我们可以找到,是调用存储过程proc_testlog导致占用了大量的日志,从而找出导致日志满的罪魁祸首。

  解决方案

  首先,尽量规避超大事务的操作,对于必须执行的这种大操作,可以考虑是否可以分解成几个事务进行,如果可以,尽量分解为小事务的方式进行;如果业务上不可以分解,是否可以考虑采用不记日志的方式?比如,load代替insert?表针对这个操作,暂时改为不记日志的方式等等。

  注意:当进行不记日志的操作时,必须非常清楚这样的操作的影响,比如,归档日志下数据库前滚的影响,hadr与复制的数据同步影响,操作失败结果如何等等。

  其次,总有些我们无法预料的操作发生,可能某个维护人员某天发出一个不适当的命令,删除了大量的数据,导致日志满,整个系统无法运行,如何规避这样的操作带来的系统运行影响呢?可以设置参数:max_log和DB2_FORCE_APP_ON_MAX_LOG注册变量。

  max_log此参数指示一个事务可以消耗的主日志空间的百分比。该值是为 logprimary 配置参数指定的值的百分比。如果该值设置为 0,那么对一个事务可以消耗的总的主日志空间的百分比没有限制。我们可以配合设置DB2_FORCE_APP_ON_MAX_LOG注册变量来规定如果应用程序违反了 max_log 配置,我们对该应用如何处理,DB2_FORCE_APP_ON_MAX_LOG设置为true,则超过max_log的应用回被强制与数据库断开连接,事务将被回滚,并且将返回错误 SQL1224N。如果 DB2_FORCE_APP_ON_MAX_LOG 注册表变量设置为 FALSE,则违反了max_log设置的的事务将失败,并返回错误 SQL0964N。该应用程序仍然可以提交在工作单元中由先前语句完成的工作,它也可以回滚已完成的工作以撤销该工作单元。

  通过次设置我们可以保证即使有大事务操作,总有(1-max_log/100)*log_primary+log_second的日志可以用来处理日常交易,从而避免系统中断。

  注意: 由 max_log 配置参数施加的限制不适用于下列 DB2 命令:ARCHIVE LOG、BACKUP DATABASE、LOAD、REORG TABLE(联机)、RESTORE DATABASE 和 ROLLFORWARD DATABASE。

2
相关文章