关于一次db2数据库导入功能低效问题处理历程

环境:数据库db2 9.7v  操作系统:linux(redhat6.0)

最近生产环境的上的一个前端导入功能客户反应说很慢,一开始客户那边反应怀疑是不是死锁和并发性导致,所以一开始就去查看db2diag.log日志找-911的错误

但是没有找到(如果一开始日志文件很大打不开,你可以重命名以下,之后数据库会生产一个新的log),于是又更改了db2数据库的注册变量环境配置,具体命令如下:
第一步:
使用命令db2 list db directory查看DB2上有那些数据库,连接数据库。
db2set -all -用于查看环境变量的配置
查看下面的三个变量是否开启,一般默认是不开启的。
第二步:
之后通过如下命令设置开启(具体语法可以使用db2set ?查看):
DBI1300N  db2set 显示、设置或除去 DB2 概要文件变量。
db2set [variable=[value]]
        [-g|-i instance [db-partition-number]]
        [-all]
        [-null]
        [-r [instance] [node-number]]
        [-n DAS node[-u user[-p password]]]
        [-l|-lr]
        [-v]
        [-ul|-ur]
        [-?|-h]


说明: 
命令选项是: 
-g       访问全局概要文件变量。
-i       指定要使用的实例概要文件,而不是当前的或缺省的实例概要文件。
-n       指定远程 DB2 管理服务器节点名。
-u       指定用于管理服务器连接的用户标识。
-ul      访问用户概要文件变量
-ur      刷新用户概要文件变量
-p       指定用于管理服务器连接的密码。
-r       复位给定实例的概要文件注册表。如果未提供任何实例,那么将使用缺
        省/当前实例。
-l       列示所有实例概要文件。
-lr      列示所有受支持的注册表变量。
-v       详细方式。
-?       显示命令帮助消息。
-h       与 -? 选项相同。
-all     显示出现的所有本地环境变量,如以下各项中所定义: 
         *  环境,用 [e] 表示
         *  用户级注册表,用 [u] 表示
         *  节点级注册表,用 [n] 表示
         *  实例级注册表,用 [i] 表示,和
         *  全局级注册表,用 [g] 表示
-null    在指定的注册表级别将变量值设置为空(null),以防止查找在变量值
         搜索顺序中定义的下一个注册表级别中的值。
注意: 
*  不带变量名的 db2set 将显示定义的所有变量。
*  db2set <变量>  将显示 <变量> 的值。
*  db2set <变量>= (无内容)  将删除 <变量>。
*  db2set <变量>=<值>  将修改 <变量> 的值。
*  db2set <变量> -null  将 <变量> 的值设置为 NULL。
*  db2set <变量> -all  将显示所有定义的 <变量> 的值。
*  db2set -ur  将刷新当前的用户概要文件。
*  db2set <变量> -ul  将显示在用户级别的定义的 <变量>。
*  db2set -all  将显示所有注册表级别中的所有定义的变量。
开启命令:
db2set DB2_EVALUNCOMMITTED=ON - i 这个参数将在记录锁之前进行谓词检查,尽量减少锁的时间;
db2set DB2_SKIPINSERTED=ON - i    这个参数将新insert且没有提交的数据跳过;例如,SELECT/UPDATE语句不会发现这条记录;
db2set DB2_SKIPDELETED=ON - i     这个参数将新delete且没有提交的数据跳过;例如,SELECT/UPDATE语句不等待这条记录的提交,并且认为他已经被删除了。
关闭命令:
db2set DB2_SKIPDELETED=
如果不加-i可能会覆盖掉db2comm=tcpip导致其他客户端机器连接不上数据库,具体到java前端就会报500错误(500错误有多种,具体查看你们自己前端服务器写的启动日志)
如果发生重新设置回来即可,这些设置需要重启db2数据库,命令如下:
db2 force application all
db2stop
db2start
第三步:重启成功后发现前端导入数据还是很慢(比原先快了那么一丢丢,开启这些命令也会导致一些问题,具体要看公司业务)。
到这时候看没有死锁,跟并发性设置关系也不大,然后准备抓取数据库快照分析下。






第一步:查看开启使用数据库快照来抓取数据库的信息
通过命令db2 get monitor switches查看快照开启信息,如下命令是开启(开启会影响数据库性能,时间自定,用完之后记得关闭,on改为off即可)
第二步:
db2 update monitor switches using lock on
第三步:
db2 get snapshot for locks on dbname > /pas/log.out(可把locks改为all,这样就可以查看更多信息,locks只看锁),log.out文件部分内容


Application handle                         = 2888
Application ID                             = 199.9.39.11.5634.150915090917
Sequence number                            = 06373
Application name                           = db2jcc_application
CONNECT Authorization ID                   = PAS
Application status                         = UOW Executing--正在执行
Status change time                         = Not Collected
Application code page                      = 1208
Locks held                                 = 9
Total wait time (ms)                       = 0


List Of Locks(有这个表示在上面的连接下锁了那些表)
 Lock Name                   = 0x010031010F0054010000000052
 Lock Attributes             = 0x00000000
 Release Flags               = 0x40000000
 Lock Count                  = 1
 Hold Count                  = 0
 Lock Object Name            = 22282255
 Object Type                 = Row  --行锁
 Tablespace Name             = TBS_SPA --表空间名
 Table Schema                = SPA
 Table Name                  = tablenam1 --表名
 Mode                        = X       --锁类型


 
Application handle                         = 434
Application ID                             = 199.9.39.11.377.1509141
Sequence number                            = 01949
Application name                           = db2jcc_application
CONNECT Authorization ID                   = PAS
Application status                         = UOW Waiting--在等待的连接
Status change time                         = Not Collected
Application code page                      = 1208
Locks held                                 = 0
Total wait time (ms)                       = 0
之后发现了很多连接处于等待状态(锁表太久跟sql语句有直接关联??初步怀疑sql语句),而且有好些表处于行锁x以及表锁ix上,于是就想通过设置锁等待时间以及LOCKLIST和MAXLOCKS来处理。具体如下步骤:
第一步:
db2 -v update monitor switches using lock on
db2 -v terminate
第二步:
然后收集数据库快照(把信息输入到pas下面的log.out文件里):
db2 -v get snapshot for database on dbname | grep –i lock >/pas/log.out
在快照输出中,检查下列各项:
Locks held currently = 21224
Lock waits = 24683
Time database waited on locks (ms) = 32875
Lock list memory in use (Bytes) = 87224
Deadlocks detected = 89
Lock escalations = 8
Exclusive lock escalations = 12
Agents currently waiting on locks = 0
Lock Timeouts = 0
Internal rollbacks due to deadlock = 0
如果“Lock list memory in use (Bytes)”超过定义的LOCKLIST大小的50%,那么就增加LOCKLIST数据库配置参数中的4KB页的数量。
如果发生了“Lock escalations>0”或“Exclusive lock escalations>0”,
则应该或者增大LOCKLIST或者MAXLOCKS,抑或同时增大两者。
查看“Locks held currently”、“Lock waits”、“Time database waited on locks (ms)”、
“Agents currently waiting on locks”和“Deadlocks detected”中是否存在高值,如果有的话,
就可能是差于最优访问计划、事务时间较长或者应用程序并发问题的症状。
LOCKLIST和MAXLOCKS的值和设置参考下面的文档:
http://wenku.baidu.com/link?url=jw7BMdUHtcISvFq_kWhyC_GxMrsCXh8PTaZgzcL7c3X2xOXLKyU99dxxrz9OWnXT6-d8BF9jTptCdMIgHAu7Z-RbAGr4g0DnYGFv2ew0z57
走到了这一步之后发现还是行不通,导入数据依然要些时间,看来导入跟数据库设置关系不大,应该是sql语句的问题。
于是就导入一条数据,然后监视
第一步:
通过db2top -d 数据库名 -u 用户名 -p 密码 命令来监视运行的sql.
第二步:
通过db2top命令查找运行时间最长以及耗费资源最多的sql。
具体用法就不提了输入命令后上面有提示,之后找到了运行最久最耗时的sql进行了优化就快多了。


处理也就到此结束,之所以一开始没有使用db2top监视一方面是由于客户反映问题的方向,另一方面是由于这个功能其他客户也用的是一样的代码,

没曾想有人改过代码。。。。。。。

PS后记:

修改表的自增字段的起始值

db2 alter table t1 alter id restart with 11 

再重组下

reorg table t1

如果表的id是自增 可以避免自增的字段是9,10的主键冲突,这个在项目中高并发经常遇到,主要是写日志的表。


你可能感兴趣的:(DB2top监视,DB2死锁,java导入数据到DB2,db2调度任务主键冲突)