仙道彰
作者仙道彰2017-09-28 17:08
数据库开发工程师, 花旗集团

DB2活动日志满的原因、分析、处理与避免

字数 6970阅读 5839评论 2赞 8

本文简单地介绍了DB2中日志的使用、活动日志以及首个活动日志的概念、日志满的原因、日志满的诊断、处理以及避免办法

背景

DB2 Transaction Log Percent exceeds threshold. Total Log Percent=95.08 on :db2inst1:XXXXXXX:UD:BPMDB856

DB2事务日志的百分比超过阈值,XXXXXXX服务器db2inst1实例下的BPMDB856数据库日志使用达到了 95.08% ;

日志使用

下图显示了并发事务条件下,日志使用示意图

有3个并发的程序Process 1、Process 2、Process 3。每一个程序都有两个事务。蓝块代表SQL语句,红块代表commit操作,绿块代表rollback操作。每一个向下的箭头都代表日志缓冲区的数据被刷新到日志磁盘上(默认是每一次提交操作都会导致日志缓冲被刷新到磁盘上)。

在T1时刻,事务A commit,日志缓冲区被刷新到磁盘上。
在T2时刻,事务B commit,日志缓冲区被刷新到磁盘上,此时日志X使用完,但由于X中的事务C还没有提交,所以X此时还是活动日志。

在上图中,如果事务C一直没有提交操作,那么日志X将永远是首个活动日志(oldest transaction log),后续的日志也是活动日志,其他应用最终会导致日志满。

活动日志

如果一个日志中包含有未提交的事务,那么这个日志就是活动日志(也有其他情况,比如虽然所有事务已经提交,但对应的更改还没有持久化到磁盘上)。

首个活动日志(First Active Log)

第一个活动日志,首个活动日志之后的日志(也就是编号比首个活动日志大的日志)都是活动日志,可以通过数据库的snapshot查看first active log, current active log, 以及 last active log.

$ db2 get snapshot for db on sample | grep -i  "File number"
File number of first active log            = 0
File number of last active log             = 2
File number of current active log          = 0
File number of log being archived          = Not applicable

日志满原因

DB2总的可用活动日志的最大空间是有限制的,当达到限制之后,就会发生日志满的问题,限制为


(LOGPRIMARY + LOGSECOND) * LOGFILSIZ * 4KB

日志满的原因无非两种:

1.) 一个小事务hold住了首个活动日志,一直没有提交,导致首个活动日志一直是活动状态,不被释放。这个跟堵车类似,一辆车因发动机故障(事务没有提交)堵住路口(占用首个活动日志),即使后面的车都没有问题(后续事务正常提交),也无法通过路口,且会越积越多,最终导致整个路都堵满车(日志满);

2.) 有个事务非常大,迅速用尽了所有的日志;

日志满的表现:

首先应用会报出SQL0964C错误:

$ db2 "insert into test select * from test"
DB21034E  The command was processed as an SQL statement because it was not a
valid Command Line Processor command.  During SQL processing it returned:
SQL0964C  The transaction log for the database is full.  SQLSTATE=57011

其次,db2diag.log中会有以下报错

2017-03-09-17.24.50.315000+480 E3234873F644         LEVEL: Error
PID     : 8532                 TID : 13028          PROC : db2syscs.exe
INSTANCE: DB2INST1             NODE : 000           DB   : SAMPLE
APPHDL  : 0-453                APPID: *LOCAL.DB2INST1.170309092321
AUTHID  : MIAOQINGSONG         HOSTNAME: ADMINIB-PR7US3I
EDUID   : 13028                EDUNAME: db2agent (SAMPLE)
FUNCTION: DB2 UDB, data protection services, sqlpgResSpace, probe:2860
MESSAGE : ADM1823E  The active log is full and is held by application handle
"0-441".  Terminate this application by COMMIT, ROLLBACK or FORCE  APPLICATION.

日志满的处理:

1. 可以通过增加LOGSECOND的数量来增加可用的日志大小;或者增加LOGPRIMARY 的数量来增加可用的日志大小;或者改变单个日志的LOGFILSIZ的大小来增加可用的日志大小;后两者需要重启数据库才能生效;

a.增大辅助日志文件个数:

db2 update db cfg for  db_name  using LOGSECOND   n

b.增大主日志文件个数:

db2 update db cfg for  db_name  using LOGPRIMARY  n

c.增大日志文件大小:

db2 udpate db cfg for  db_name  using LOGFILSIZ    n

对于后两种方法(LOGPRIMARY / LOGFILSIZ )需要重启数据库,修改方才生效;

db2 force applications all
db2stop
db2start 

PS : (LOGPRIMARY + LOGSECOND) <= 256 , 如果这两个数值的和已经是256了(如下图所示),那么只能通过改变LOGFILSIZ的方式来增加日志的大小;

log1.jpg

log1.jpg

2. force掉hold住首个活动日志的的应用:

在force之前,可以抓取snapshot,看一下这个应用的状态:

 $ db2 get snapshot for database on sample | grep -i oldest
 Appl id holding the oldest transaction     = 441
$ db2 get snapshot for application agentid 441

Application Snapshot
Application handle                         = 441
Application status                         = UOW Waiting                 <<--应用状态为UOW Waiting
Status change time                         = 2017-03-09 17:23:15.068895
Application code page                      = 1386
Application country/region code            = 86
DUOW correlation token                     = *LOCAL.DB2INST1.170309092244
Application name                           = db2bp.exe
Application ID                             = *LOCAL.DB2INST1.170309092244

..

Connection request start timestamp         = 2017-03-09 17:22:44.963163  <<--应用连库时间
Connect request completion timestamp       = 2017-03-09 17:22:45.961157
Application idle time                      = 4 minutes  7 seconds

..

UOW log space used (Bytes)                 = 664
Previous UOW completion timestamp          = 2017-03-09 17:22:45.961157
Elapsed time of last completed uow (sec.ms)= 0.000000
UOW start timestamp                        = 2017-03-09 17:23:02.770477 <<--当前事务开始时间
UOW stop timestamp                         =                     <<--当前事务结束时间为空,说明还没有commit
UOW completion status                      =

..

Statement type                             = Dynamic SQL Statement
Statement                                  = Close
Section number                             = 201
Application creator                        = NULLID
Package name                               = SQLC2K26
Consistency Token                          =
Package Version ID                         =
Cursor name                                = SQLCUR201
Statement member number                    = 0
Statement start timestamp                  = 2017-03-09 17:23:15.067789
Statement stop timestamp                   = 2017-03-09 17:23:15.068893 
Elapsed time of last completed stmt(sec.ms)= 0.000024
Total Statement user CPU time              = 0.000000
Total Statement system CPU time            = 0.000000

..

Dynamic SQL statement text:      

select * from t1

一个事务中可能有多条SQL,这个只表示当前正在执行或者最后执行过的SQL,并不能表示就是这条SQL导致了日志满,这里抓取到的是一条SELECT语句,SELECT语句不占用日志。

$ db2 "force application (441)"
DB20000I  The FORCE APPLICATION command completed successfully.
DB21024I  This command is asynchronous and may not be effective immediately.

日志满的避免:

1).根据抓取到的应用的snapshot,找应用开发人员查看为何没有及时提交,这才是避免问题再次出现的根本办法;
2).优化占用日志空间较大的SQL ;
3).从DB2管理层面,可以设置数据库配置参数max_log和num_log_span;
4).可以写脚本,以固定的间隔抓取database snapshot中的Appl id holding the oldest transaction, 如果长时间不发生变化(比如2天),就Force掉;

查看数据库整体日志的使用强况:

a.通过管理视图查询:

 db2 " select DB_NAME, LOG_UTILIZATION_PERCENT, TOTAL_LOG_USED_KB,TOTAL_LOG_AVAILABLE_KB,TOTAL_LOG_USED_TOP_KB, DBPARTITIONNUM from SYSIBMADM.LOG_UTILIZATION  "

b.查看快照视图:

db2 " select  int(total_log_used/1024/1024) as Log_Used_Mb ,int(total_log_available/1024/1024) as Log_SpaceFree_Mb ,int((float(total_log_used)/float(total_log_used+total_log_available))*100) as Pct_Used  ,int(tot_log_used_top/1024/1024) as Max_Log_Used_Mb ,int(sec_log_used_top/1024/1024) as Max_Sec_sed_Mb ,int(sec_logs_allocated) as Secondaries from sysibmadm.snapdb  "

c.通过带入参数查看表函数的方法:

 db2 " select DB_NAME,TOTAL_LOG_AVAILABLE,TOTAL_LOG_USED,SEC_LOG_USED_TOP,SEC_LOGS_ALLOCATED from table(SNAP_GET_DB('db_name',0)) "
 

将db_name 替换成需要查询的数据的名称即可;

查看每个应用使用的日志大小:

$  db2 "select application_handle,UOW_LOG_SPACE_USED,UOW_START_TIME FROM TABLE(MON_GET_UNIT_OF_WORK(NULL,-1)) order by UOW_LOG_SPACE_USED" 


也可以通过db2pd -db <dbname> -transactions 查看每个正在使用的日志的情况

重点关注的参数有:

ApplHandl
The application handle of the transaction.
SpaceReserved
The amount of log space that is reserved for the transaction.
LogSpace
The total log space that is required for the transaction, including the used space and the reserved space for compensation log records.

参考文章:

1.MON_TRANSACTION_LOG_UTILIZATION administrative view - Retrieve log utilization information

2.max_log - Maximum log per transaction configuration parameter

3.DB2活动日志满的原因、分析、处理与避免

4.db2事务日志满,或者日志磁盘空间已满解决办法

5.如何查看db2的数据库的日志文件

声明:版权所有非经授权请勿做任何商业用途,仅限技术交流; 转载请注明出处;

如果觉得我的文章对您有用,请点赞。您的支持将鼓励我继续创作!

8

添加新评论2 条评论

wangweilongwangweilong数据库管理员, 某大
2017-10-09 13:05
谢谢分享
jxnxsdengyujxnxsdengyu系统工程师, 江西农信
2017-09-29 11:03
总结的很全面,上面两种情况都遇到过无数次了,有时满了,有时预警了,每次处理后,都很想骂应用的人。。。
Ctrl+Enter 发表

作者其他文章

相关文章

相关问题

相关资料

X社区推广