最近处理一个问题的时候,先是收到db time升高的报警,然后查看db time的情况发现,已经有近1000%的负载了。
最近处理一个问题的时候,先是收到db time升高的报警,然后查看db time的情况发现,已经有近1000%的负载了。
带着好奇心想看看到底是什么样的一个语句导致如此的情况。
先抓取了一个awr报告,因为问题发生的时间段比较集中而且时间持续有几个小时,所以抓取了一个小时的快照。
得到的awr部分内容如下:
cache sizes
beginend
buffer cache:39,472m39,472mstd block size:8k
shared pool size:1,440m1,440mlog buffer:14,256k
从下面的部分可以看出数据库其实内部的活动并不多,redo生成量不高,tps也不高。
load profile
per secondper transaction
redo size:154,276.4124,024.13
logical reads:4,864.90757.57
block changes:779.75121.42
physical reads:509.5379.35
physical writes:359.9056.04
user calls:2,658.46413.98
parses:837.89130.48
hard parses:0.090.01
sorts:171.2226.66
logons:0.470.07
executes:949.10147.80
transactions:6.42
而查看等待时间,发现第一个等待事件是db file sequential read,平均等待时间有近17ms,
延迟一般需要在10ms以下,或者至少100 reads/sec,在基于san存储缓存数据的情况下,sequential read的指标有时候会保持在2ms左右,这个只能说明san已经把数据转化为缓存了,倒不能说明硬盘驱动确实很快。这个地方已经超过了10ms说明io上还是存在较大的影响。我们先放过这个问题,继续往下看。
eventwaitstime(s)avg wait(ms)% total call timewait class
db file sequential read917,81015,3101796.1user i/o
cpu time 596 3.7
log file sync16,085186121.2commit
log file parallel write15,4661409.9system i/o
arch wait on sendreq3741027.1network
而根据时间模型来看,绝大部分的db time都在sql语句方面,所以关注sql语句就是一个很重要的部分。
statistic nametime (s)% of db time
sql execute elapsed time15,533.4397.47
db cpu596.113.74
connection management call elapsed time82.890.52
parse time elapsed20.220.13
而对于top1的sql语句让自己和吃惊,竟然是一个很简单的update.
elapsed time (s)cpu time (s)executionselap per exec (s)% total db timesql idsql modulesql text
8,6596962213.9254.34 update user_test t set t.login_status='' where t.cn_test=:1
第一感觉就是这个语句走了全表扫描,因为一个简单的update竟然需要花费近13秒的时间,,已经算很长的了。
当然猜测也需要验证,我们来看看awrsqrpt的结果。
发现这个报告还是蛮有意思。至于执行计划是走了唯一性索引扫描,所以执行计划的情况来看还是没有问题的。
idoperationnamerowsbytescost (%cpu)time
0update statement 1 (100)
1 updateuser_billing
2 index unique scanidx_user_test_cnmaster1301 (0)00:00:01
但是查看sql语句的执行统计信息,就有些奇怪了。
stat namestatement totalper execution% snap total
elapsed time (ms)8,659,18013,921.5154.34
cpu time (ms)69,346111.4911.63
executions622
buffer gets3,146,0685,057.9935.91
disk reads645,2291,037.3570.31
parse calls6221.000.04
rows621,827999.72
user i/o wait time (ms)8,608,075
sql语句的执行总共持续8659s左右,然后8608s的时间在user i/o的等待上,这样下来,622次的执行其实花费的时间并不多。
对于这个问题,自己也比较疑惑,开始怀疑是否是磁盘的io上出现了问题。
但是使用megacli查看的时候,发现不存在任何的坏块。
# megacli -cfgdsply -a0|grep error
media error count: 0
other error count: 0
media error count: 0
other error count: 0
media error count: 0
other error count: 0
media error count: 0
other error count: 0
media error count: 0
other error count: 0
media error count: 0
other error count: 0
media error count: 0
这个时候的一个猜测就是可能由绑定变量的数据类型不同导致的sql性能问题。但是排查一番,发现还是没有得到自己期望的结果。
查看输入的参数类型,都是期望中的varchar2,所以sql语句的过程中还是不会出现自己猜想的全表扫描的可能性。
select name,datatype_string,value_string,datatype from dba_hist_sqlbind where sql_id='94p345yuqh3zd' and snap_id between 58711 and 58712
name datatype_string value_string datatype
------------------------------ --------------- ------------------------------ ----------
:1 varchar2(128) xxxxxx9@test.com 1
:1 varchar2(128) 23234324324234 1
对于io的瓶颈问题,自己还是从addm中得到了自己需要的东西。
对于磁盘吞吐量的说法,addm的报告中是这么描述的。
finding 6: 39% impact (6136 seconds)
------------------------------------
the throughput of the i/o subsystem was significantly lower than expected.