AWR报告详细分析
AWR 是Oracle 10g 版本 推出的新特性, 全称叫Automatic Workload Repository-自动负载信息库, AWR 是通过对比两次快,照(snapshot)收集到的统计信息,来生成报表数据,生成的报表包括多个部分。
WORKLOAD REPOSITORY report for
DB Name |
DB Id |
Instance |
Inst num |
Release |
RAC |
Host |
ICCI |
1314098396 |
ICCI1 |
1 |
10.2.0.3.0 |
YES |
HPGICCI1 |
|
Snap Id |
Snap Time |
Sessions |
Cursors/Session |
Begin Snap: |
2678 |
25-Dec-08 14:04:50 |
24 |
1.5 |
End Snap: |
2680 |
25-Dec-08 15:23:37 |
26 |
1.5 |
Elapsed: |
|
78.79 (mins) |
|
|
DB Time: |
|
11.05 (mins) |
|
|
DB Time不包括Oracle后台进程消耗的时间。如果DB Time远远小于Elapsed时间,说明数据库比较空闲。
db time= cpu time + wait time(不包含空闲等待)(非后台进程)
说白了就是db time就是记录的服务器花在数据库运算(非后台进程)和等待(非空闲等待)上的时间
DB time = cputime + all of nonidle wait event time
在79分钟里(其间收集了3次快照数据),数据库耗时11分钟,RDA数据中显示系统有8个逻辑CPU(4个物理CPU),平均每个CPU耗时1.4分钟,CPU利用率只有大约2%(1.4/79)。说明系统压力非常小。
列出下面这两个来做解释:
Report A:
Snap Id Snap Time Sessions Curs/Sess
--------- ------------------- -------- ---------
Begin Snap: 4610 24-Jul-08 22:00:54 68 19.1
End Snap: 4612 24-Jul-08 23:00:25 17 1.7
Elapsed: 59.51 (mins)
DB Time: 466.37 (mins)
Report B:
Snap Id Snap Time Sessions Curs/Sess
--------- ------------------- -------- ---------
Begin Snap: 3098 13-Nov-07 21:00:37 39 13.6
End Snap: 3102 13-Nov-07 22:00:15 40 16.4
Elapsed: 59.63 (mins)
DB Time: 19.49 (mins)
服务器是AIX的系统,4个双核cpu,共8个核:
/sbin> bindprocessor -q
The available processors are: 0 1 2 3 4 5 6 7
先说ReportA,在snapshot间隔中,总共约60分钟,cpu就共有60*8=480分钟,DBtime为466.37分钟,则:
cpu花费了466.37分钟在处理Oralce非空闲等待和运算上(比方逻辑读)
也就是说cpu有 466.37/480*100% 花费在处理Oracle的操作上,这还不包括后台进程
看Report B,总共约60分钟,cpu有19.49/480*100% 花费在处理Oracle的操作上
很显然,2中服务器的平均负载很低。
从awr report的Elapsed time和DBTime就能大概了解db的负载。
可是对于批量系统,数据库的工作负载总是集中在一段时间内。如果快照周期不在这一段时间内,或者快照周期跨度太长而包含了大量的数据库空闲时间,所得出的分析结果是没有意义的。这也说明选择分析时间段很关键,要选择能够代表性能问题的时间段。
ReportSummary
Cache Sizes
|
Begin |
End |
|
|
Buffer Cache: |
3,344M |
3,344M |
Std Block Size: |
8K |
Shared Pool Size: |
704M |
704M |
Log Buffer: |
14,352K |
显示SGA中每个区域的大小(在AMM改变它们之后),可用来与初始参数值比较。
shared pool主要包括library cache和dictionary cache。library cache用来存储最近解析(或编译)后SQL、PL/SQL和Java classes等。library cache用来存储最近引用的数据字典。发生在library cache或dictionary cache的cache miss代价要比发生在buffer cache的代价高得多。因此shared pool的设置要确保最近使用的数据都能被cache。
Load Profile
|
Per Second |
Per Transaction |
Redo size: |
918,805.72 |
775,912.72 |
Logical reads: |
3,521.77 |
2,974.06 |
Block changes: |
1,817.95 |
1,535.22 |
Physical reads: |
68.26 |
57.64 |
Physical writes: |
362.59 |
306.20 |
User calls: |
326.69 |
275.88 |
Parses: |
38.66 |
32.65 |
Hard parses: |
0.03 |
0.03 |
Sorts: |
0.61 |
0.51 |
Logons: |
0.01 |
0.01 |
Executes: |
354.34 |
299.23 |
Transactions: |
1.18 |
|
% Blocks changed per Read: |
51.62 |
Recursive Call %: |
51.72 |
Rollback per transaction %: |
85.49 |
Rows per Sort: |
######## |
显示数据库负载概况,将之与基线数据比较才具有更多的意义,如果每秒或每事务的负载变化不大,说明应用运行比较稳定。单个的报告数据只说明应用的负载情况,绝大多数据并没有一个所谓“正确”的值,然而Logons大于每秒1~2个、Hardparses大于每秒100、全部parses超过每秒300表明可能有争用问题。
Redo size:每秒产生的日志大小(单位字节),可标志数据变更频率, 数据库任务的繁重与否。Logical reads:每秒/每事务逻辑读的块数.平决每秒产生的逻辑读的block数。Logical Reads= Consistent Gets + DBBlock Gets
Block changes:每秒/每事务修改的块数
Physical reads:每秒/每事务物理读的块数
Physical writes:每秒/每事务物理写的块数
User calls:每秒/每事务用户call次数
Parses:SQL解析的次数.每秒解析次数,包括fastparse,soft parse和hard parse三种数量的综合。 软解析每秒超过300次意味着你的"应用程序"效率不高,调整session_cursor_cache。在这里,fast parse指的是直接在PGA中命中的情况(设置了session_cached_cursors=n);soft parse是指在sharedpool中命中的情形;hard parse则是指都不命中的情况。
Hard parses:其中硬解析的次数,硬解析太多,说明SQL重用率不高。每秒产生的硬解析次数, 每秒超过100次,就可能说明你绑定使用的不好,也可能是共享池设置不合理。这时候可以启用参数cursor_sharing=similar|force,该参数默认值为exact。但该参数设置为similar时,存在bug,可能导致执行计划的不优。
Sorts:每秒/每事务的排序次数
Logons:每秒/每事务登录的次数
Executes:每秒/每事务SQL执行次数
Transactions:每秒事务数.每秒产生的事务数,反映数据库任务繁重与否。
Blocks changed per Read:表示逻辑读用于修改数据块的比例.在每一次逻辑读中更改的块的百分比。
Recursive Call:递归调用占所有操作的比率.递归调用的百分比,如果有很多PL/SQL,那么这个值就会比较高。
Rollback pertransaction:每事务的回滚率.看回滚率是不是很高,因为回滚很耗资源 ,如果回滚率过高,可能说明你的数据库经历了太多的无效操作 ,过多的回滚可能还会带来Undo Block的竞争 该参数计算公式如下: Round(Userrollbacks / (user commits + user rollbacks) ,4)* 100% 。
Rows per Sort:每次排序的行数
注:
Oracle的硬解析和软解析
提到软解析(soft prase)和硬解析(hard prase),就不能不说一下Oracle对sql的处理过程。当你发出一条sql语句交付Oracle,在执行和获取结果前,Oracle对此sql将进行几个步骤的处理过程:
1、语法检查(syntax check)
检查此sql的拼写是否语法。
2、语义检查(semantic check)
诸如检查sql语句中的访问对象是否存在及该用户是否具备相应的权限。
3、对sql语句进行解析(prase)
利用内部算法对sql进行解析,生成解析树(parse tree)及执行计划(execution plan)。
4、执行sql,返回结果(execute and return)
其中,软、硬解析就发生在第三个过程里。
Oracle利用内部的hash算法来取得该sql的hash值,然后在librarycache里查找是否存在该hash值;
假设存在,则将此sql与cache中的进行比较;
假设“相同”,就将利用已有的解析树与执行计划,而省略了优化器的相关工作。这也就是软解析的过程。
诚然,如果上面的2个假设中任有一个不成立,那么优化器都将进行创建解析树、生成执行计划的动作。这个过程就叫硬解析。
创建解析树、生成执行计划对于sql的执行来说是开销昂贵的动作,所以,应当极力避免硬解析,尽量使用软解析。
Instance Efficiency Percentages (Target 100%)
Buffer Nowait %: |
100.00 |
Redo NoWait %: |
100.00 |
Buffer Hit %: |
98.72 |
In-memory Sort %: |
99.86 |
Library Hit %: |
99.97 |
Soft Parse %: |
99.92 |
Execute to Parse %: |
89.09 |
Latch Hit %: |
99.99 |
Parse CPU to Parse Elapsd %: |
7.99 |
% Non-Parse CPU: |
99.95 |
本节包含了Oracle关键指标的内存命中率及其它数据库实例操作的效率。其中Buffer HitRatio 也称Cache HitRatio,Library Hitratio也称LibraryCache Hit ratio。同Load Profile一节相同,这一节也没有所谓“正确”的值,而只能根据应用的特点判断是否合适。在一个使用直接读执行大型并行查询的DSS环境,20%的Buffer Hit Ratio是可以接受的,而这个值对于一个OLTP系统是完全不能接受的。根据Oracle的经验,对于OLTP[FF1] 系统,Buffer Hit Ratio理想应该在90%以上。
Buffer Nowait表示在内存获得数据的未等待比例。在缓冲区中获取Buffer的未等待比率。Buffer Nowait的这个值一般需要大于99%。否则可能存在争用,可以在后面的等待事件中进一步确认。
buffer hit表示进程从内存中找到数据块的比率,监视这个值是否发生重大变化比这个值本身更重要。对于一般的OLTP系统,如果此值低于80%,应该给数据库分配更多的内存。数据块在数据缓冲区中的命中率,通常应在95%以上。否则,小于95%,需要调整重要的参数,小于90%可能是要加db_cache_size。一个高的命中率,不一定代表这个系统的性能是最优的,比如大量的非选择性的索引被频繁访问,就会造成命中率很高的假相(大量的dbfile sequential read),但是一个比较低的命中率,一般就会对这个系统的性能产生影响,需要调整。命中率的突变,往往是一个不好的信息。如果命中率突然增大,可以检查top buffer get SQL,查看导致大量逻辑读的语句和索引,如果命中率突然减小,可以检查top physical reads SQL,检查产生大量物理读的语句,主要是那些没有使用索引或者索引被删除的。
Redo NoWait表示在LOG缓冲区获得BUFFER的未等待比例。如果太低(可参考90%阀值),考虑增加LOG BUFFER。当redobuffer达到1M时,就需要写到redo log文件,所以一般当redo buffer设置超过1M,不太可能存在等待buffer空间分配的情况。当前,一般设置为2M的redo buffer,对于内存总量来说,应该不是一个太大的值。
library hit表示Oracle从Library Cache中检索到一个解析过的SQL或PL/SQL语句的比率,当应用程序调用SQL或存储过程时,Oracle检查Library Cache确定是否存在解析过的版本,如果存在,Oracle立即执行语句;如果不存在,Oracle解析此语句,并在Library Cache中为它分配共享SQL区。低的library hit ratio会导致过多的解析,增加CPU消耗,降低性能。如果library hit ratio低于90%,可能需要调大sharedpool区。STATEMENT在共享区的命中率,通常应该保持在95%以上,否则需要要考虑:加大共享池;使用绑定变量;修改cursor_sharing等参数。
Latch Hit:Latch是一种保护内存结构的锁,可以认为是SERVER进程获取访问内存数据结构的许可。要确保Latch Hit>99%,否则意味着Shared Pool latch争用,可能由于未共享的SQL,或者LibraryCache太小,可使用绑定变更或调大SharedPool解决。要确保>99%,否则存在严重的性能问题。当该值出现问题的时候,我们可以借助后面的等待时间和latch分析来查找解决问题。
Parse CPU to ParseElapsd:解析实际运行时间/(解析实际运行时间+解析中等待资源时间),越高越好。计算公式为:Parse CPU to Parse Elapsd %= 100*(parse time cpu / parse timeelapsed)。即:解析实际运行时间/(解析实际运行时间+解析中等待资源时间)。如果该比率为100%,意味着CPU等待时间为0,没有任何等待。
Non-Parse CPU :SQL实际运行时间/(SQL实际运行时间+SQL解析时间),太低表示解析消耗时间过多。计算公式为:% Non-Parse CPU =round(100*1-PARSE_CPU/TOT_CPU),2)。如果这个值比较小,表示解析消耗的CPU时间过多。与PARSE_CPU相比,如果TOT_CPU很高,这个比值将接近100%,这是很好的,说明计算机执行的大部分工作是执行查询的工作,而不是分析查询的工作。
Execute to Parse:是语句执行与分析的比例,如果要SQL重用率高,则这个比例会很高。该值越高表示一次解析后被重复执行的次数越多。计算公式为:Execute to Parse =100 *(1 - Parses/Executions)。本例中,差不多每execution 5次需要一次parse。所以如果系统Parses > Executions,就可能出现该比率小于0的情况。该值<0通常说明shared pool设置或者语句效率存在问题,造成反复解析,reparse可能较严重,或者是可能同snapshot有关,通常说明数据库性能存在问题。
In-memory Sort:在内存中排序的比率,如果过低说明有大量的排序在临时表空间中进行。考虑调大PGA(10g)。如果低于95%,可以通过适当调大初始化参数PGA_AGGREGATE_TARGET或者SORT_AREA_SIZE来解决,注意这两个参数设置作用的范围时不同的,SORT_AREA_SIZE是针对每个session设置的,PGA_AGGREGATE_TARGET则时针对所有的sesion的。
Soft Parse:软解析的百分比(softs/softs+hards),近似当作sql在共享区的命中率,太低则需要调整应用使用绑定变量。sql在共享区的命中率,小于<95%,需要考虑绑定,如果低于80%,那么就可以认为sql基本没有被重用。
Shared Pool Statistics
|
Begin |
End |
Memory Usage %: |
47.19 |
47.50 |
% SQL with executions>1: |
88.48 |
79.81 |
% Memory for SQL w/exec>1: |
79.99 |
73.52 |
Memory Usage %:对于一个已经运行一段时间的数据库来说,共享池内存使用率,应该稳定在75%-90%间,如果太小,说明SharedPool有浪费,而如果高于90,说明共享池中有争用,内存不足。这个数字应该长时间稳定在75%~90%。如果这个百分比太低,表明共享池设置过大,带来额外的管理上的负担,从而在某些条件下会导致性能的下降。如果这个百分率太高,会使共享池外部的组件老化,如果SQL语句被再次执行,这将使得SQL语句被硬解析。在一个大小合适的系统中,共享池的使用率将处于75%到略低于90%的范围内.
SQL with executions>1:执行次数大于1的sql比率,如果此值太小,说明需要在应用中更多使用绑定变量,避免过多SQL解析。在一个趋向于循环运行的系统中,必须认真考虑这个数字。在这个循环系统中,在一天中相对于另一部分时间的部分时间里执行了一组不同的SQL语句。在共享池中,在观察期间将有一组未被执行过的SQL语句,这仅仅是因为要执行它们的语句在观察期间没有运行。只有系统连续运行相同的SQL语句组,这个数字才会接近100%。
Memory for SQL w/exec>1:执行次数大于1的SQL消耗内存的占比。这是与不频繁使用的SQL语句相比,频繁使用的SQL语句消耗内存多少的一个度量。这个数字将在总体上与% SQL withexecutions>1非常接近,除非有某些查询任务消耗的内存没有规律。在稳定状态下,总体上会看见随着时间的推移大约有75%~85%的共享池被使用。如果Statspack报表的时间窗口足够大到覆盖所有的周期,执行次数大于一次的SQL语句的百分率应该接近于100%。这是一个受观察之间持续时间影响的统计数字。可以期望它随观察之间的时间长度增大而增大。
小结:通过ORACLE的实例有效性统计数据,我们可以获得大概的一个整体印象,然而我们并不能由此来确定数据运行的性能。当前性能问题的确定,我们主要还是依靠下面的等待事件来确认。我们可以这样理解两部分的内容,hit统计帮助我们发现和预测一些系统将要产生的性能问题,由此我们可以做到未雨绸缪。而wait事件,就是表明当前数据库已经出现了性能问题需要解决,所以是亡羊补牢的性质。
Top 5 Timed Events
Event |
Waits |
Time(s) |
Avg Wait(ms) |
% Total Call Time |
Wait Class |
CPU time |
|
515 |
|
77.6 |
|
SQL*Net more data from client |
27,319 |
64 |
2 |
9.7 |
Network |
log file parallel write |
5,497 |
47 |
9 |
7.1 |
System I/O |
db file sequential read |
7,900 |
35 |
4 |
5.3 |
User I/O |
db file parallel write |
4,806 |
34 |
7 |
5.1 |
System I/O |
这是报告概要的最后一节,显示了系统中最严重的5个等待,按所占等待时间的比例倒序列示。当我们调优时,总希望观察到最显著的效果,因此应当从这里入手确定我们下一步做什么。例如如果‘bufferbusy wait’是较严重的等待事件,我们应当继续研究报告中Buffer Wait和File/TablespaceIO区的内容,识别哪些文件导致了问题。如果最严重的等待事件是I/O事件,我们应当研究按物理读排序的SQL语句区以识别哪些语句在执行大量I/O,并研究Tablespace和I/O区观察较慢响应时间的文件。如果有较高的LATCH等待,就需要察看详细的LATCH统计识别哪些LATCH产生的问题。
一个性能良好的系统,cputime应该在top 5的前面,否则说明你的系统大部分时间都用在等待上。
在这里,log fileparallel write是相对比较多的等待,占用了7%的CPU时间。
通常,在没有问题的数据库中,CPUtime总是列在第一个。
更多的等待事件,参见本报告 的Wait Events一节。
RACStatistics
|
Begin |
End |
Number of Instances: |
2 |
2 |
Global Cache Load Profile
|
Per Second |
Per Transaction |
Global Cache blocks received: |
4.16 |
3.51 |
Global Cache blocks served: |
5.97 |
5.04 |
GCS/GES messages received: |
408.47 |
344.95 |
GCS/GES messages sent: |
258.03 |
217.90 |
DBWR Fusion writes: |
0.05 |
0.05 |
Estd Interconnect traffic (KB) |
211.16 |
|
Global Cache Efficiency Percentages (Target local+remote 100%)
Buffer access - local cache %: |
98.60 |
Buffer access - remote cache %: |
0.12 |
Buffer access - disk %: |
1.28 |
Global Cache and Enqueue Services - Workload Characteristics
Avg global enqueue get time (ms): |
0.1 |
Avg global cache cr block receive time (ms): |
1.1 |
Avg global cache current block receive time (ms): |
0.8 |
Avg global cache cr block build time (ms): |
0.0 |
Avg global cache cr block send time (ms): |
0.0 |
Global cache log flushes for cr blocks served %: |
3.5 |
Avg global cache cr block flush time (ms): |
3.9 |
Avg global cache current block pin time (ms): |
0.0 |
Avg global cache current block send time (ms): |
0.0 |
Global cache log flushes for current blocks served %: |
0.4 |
Avg global cache current block flush time (ms): |
3.0 |
Global Cache and Enqueue Services - Messaging Statistics
Avg message sent queue time (ms): |
0.0 |
Avg message sent queue time on ksxp (ms): |
0.3 |
Avg message received queue time (ms): |
0.5 |
Avg GCS message process time (ms): |
0.0 |
Avg GES message process time (ms): |
0.0 |
% of direct sent messages: |
14.40 |
% of indirect sent messages: |
77.04 |
% of flow controlled messages: |
8.56 |
- Wait Events Statistics
- SQL Statistics
- Instance Activity Statistics
- IO Stats
- Buffer Pool Statistics
- Advisory Statistics
- Wait Statistics
- Undo Statistics
- Latch Statistics
- Segment Statistics
- Dictionary Cache Statistics
- Library Cache Statistics
- Memory Statistics
- Streams Statistics
- Resource Limit Statistics
- init.ora Parameters
Wait Events Statistics
- Time Model Statistics
- Wait Class
- Wait Events
- Background Wait Events
- Operating System Statistics
- Service Statistics
- Service Wait Class Stats
/* oracle等待事件是衡量oracle运行状况的重要依据及指示,等待事件分为两类:空闲等待事件和非空闲等待事件, TIMED_STATISTICS = TRUE 那么等待事件按等待的时间排序,=FALSE那么事件按等待的数量排序。运行statspack期间必须session上设置TIMED_STATISTICS = TRUE,否则统计的数据将失真。空闲等待事件是oracle正等待某种工作,在诊断和优化数据库时候,不用过多注意这部分事件,非空闲等待事件专门针对oracle的活动,指数据库任务或应用程序运行过程中发生的等待,这些等待事件是我们在调整数据库应该关注的。
对于常见的等待事件,说明如下:
1) db file scattered read 文件分散读取
该事件通常与全表扫描或者fast full index scan有关。因为全表扫描是被放入内存中进行的进行的,通常情况下基于性能的考虑,有时候也可能是分配不到足够长的连续内存空间,所以会将数据块分散(scattered)读入Buffer Cache中。该等待过大可能是缺少索引或者没有合适的索引(可以调整optimizer_index_cost_adj) 。这种情况也可能是正常的,因为执行全表扫描可能比索引扫描效率更高。当系统存在这些等待时,需要通过检查来确定全表扫描是否必需的来调整。因为全表扫描被置于LRU(Least Recently Used,最近最少适用)列表的冷端(cold end),对于频繁访问的较小的数据表,可以选择把他们Cache 到内存中,以避免反复读取。当这个等待事件比较显著时,可以结合v$session_longops 动态性能视图来进行诊断,该视图中记录了长时间(运行时间超过6 秒的)运行的事物,可能很多是全表扫描操作(不管怎样,这部分信息都是值得我们注意的)。
关于参数OPTIMIZER_INDEX_COST_ADJ=n:该参数是一个百分比值,缺省值为100,可以理解为FULL SCAN COST/INDEX SCAN COST。当n%* INDEX SCAN COST<FULL SCAN COST时,oracle会选择使用索引。在具体设置的时候,我们可以根据具体的语句来调整该值。如果我们希望某个statement使用索引,而实际它确走全表扫描,可以对比这两种情况的执行计划不同的COST,从而设置一个更合适的值。
2) db file sequential read 文件顺序读取整代码,特别是表连接:该事件说明在单个数据块上大量等待,该值过高通常是由于表间连接顺序很糟糕(没有正确选择驱动行源),或者使用了非选择性索引。通过将这种等待与statspack报表中已知其它问题联系起来(如效率不高的sql),通过检查确保索引扫描是必须的,并确保多表连接的连接顺序来调整。
3) buffer busy wait 缓冲区忙 增大DB_CACHE_SIZE,加速检查点,调整代码:
当进程需要存取SGA中的buffer的时候,它会依次执行如下步骤的操作:
当缓冲区以一种非共享方式或者如正在被读入到缓冲时,就会出现该等待。该值不应该大于1%。当出 现等待问题时,可以检查缓冲等待统计部分(或V$WAITSTAT),确定该等待发生在什么位置:
a) 如果等待是否位于段头(Segment Header)。这种情况表明段中的空闲列表(freelist)的块比较少。可以考虑增加空闲列表(freelist,对于Oracle8i DMT)或者增加freelist groups(在很多时候这个调整是立竿见影的(alter table tablename strorage(freelists 2)),在8.1.6之前,这个freelists参数不能动态修改;在8.1.6及以后版本,动态修改feelists需要设置COMPATIBLE至少为8.1.6)。也可以增加PCTUSED与PCTFREE之间距离(PCTUSED-to-pctfreegap),其实就是说降低PCTUSED的值,尽快使块返回freelist列表被重用。如果支持自动段空间管理(ASSM),也可以使用ASSM模式,这是在ORALCE 920以后的版本中新增的特性。
b) 如果这一等待位于undo header,可以通过增加回滚段(rollback segment)来解决缓冲区的问题。
c) 如果等待位于undo block上,我们需要增加提交的频率,使block可以尽快被重用;使用更大的回滚段;降低一致读所选择的表中数据的密度;增大DB_CACHE_SIZE。
d) 如果等待处于data block,表明出现了hotblock,可以考虑如下方法解决: ①将频繁并发访问的表或数据移到另一数据块或者进行更大范围的分布(可以增大pctfree值 ,扩大数据分布,减少竞争),以避开这个"热点"数据块。②也可以减小数据块的大小,从而减少一个数据块中的数据行数,降低数据块的热度,减小竞争;③检查对这些热块操作的SQL语句,优化语句。④增加hot block上的initrans值。但注意不要把initrans值设置的过于高了,通常设置为5就足够了。因为增加事务意味着要增加ITL事务槽,而每个ITL事务槽将占用数据块中24个字节长度。默认情况下,每个数据块或者索引块中是ITL槽是2个,在增加initrans的时候,可以考虑增大数据块所在的表的PCTFREE值,这样Oracle会利用PCTFREE部分的空间增加ITL slot数量,最大达到maxtrans指定。
e) 如果等待处于index block,应该考虑重建索引、分割索引或使用反向键索引。为了防止与数据块相关的缓冲忙等待,也可以使用较小的块,在这种情况下,单个块中的记录就较少,所以这个块就不是那么"繁忙"。或者可以设置更大的PCTFREE,使数据扩大物理分布,减少记录间的热点竞争。在执行DML(insert/update/ delete)时,Oracle向数据块中写入信息,对于多事务并发访问的数据表,关于ITL的竞争和等待可能出现,为了减少这个等待,可以增加initrans,使用多个ITL槽。在Oracle9i 中,可以使用ASSM这个新特性Oracle 使用位图来管理空间使用,减小争用。
【
当进程需要存取SGA中的buffer的时候,它会依次执行如下步骤的操作:
1.获得cache buffers chains latch,遍历那条buffer chain直到找到需要的buffer header
2.根据需要进行的操作类型(读或写),它需要在buffer header上获得一个共享或独占模式的buffer pin或者buffer lock
3.若进程获得buffer header pin,它会释放获得的cache buffers chains latch,然后执行对buffer block的操作
4.若进程无法获得buffer header pin,它就会在buffer busy waits事件上等待
进程之所以无法获得buffer header pin,是因为为了保证数据的一致性,同一时刻一个block只能被一个进程pin住进行存取,因此当一个进程需要存取buffer cache中一个被其他进程使用的block的时候,这个进程就会产生对该block的buffer busy waits事件。
截至Oracle 9i,buffer busy waits事件的p1,p2,p3三个参数分别是file#,block#和id,分别表示等待的buffer block所在的文件编号,块编号和具体的等待原因编号,到了Oracle 10g,前两个参数没变,第3个参数变成了块类型编号,这一点可以通过查询v$event_name视图来进行验证:
PHP code:
Oracle 9i
SQL> select parameter1,parameter2,parameter3 from v$event_name where name='buffer busy waits'
PARAMETER1 PARAMETER2 PARAMETER3
------------------------ ------------------------------------------------
file# block# id
Oracle 10g
PARAMETER1 PARAMETER2 PARAMETER3
------------------------ ------------------------------------------------
file# block# class#
在诊断buffer busy waits事件的过程中,获取如下信息会很有用:
1.获取产生buffer busy waits事件的等待原因编号,这可以通过查询该事件的p3参数值获得
2.获取产生此事件的SQL语句,可以通过如下的查询获得:
select sql_text from v$sql t1,v$session t2,v$session_wait t3
where t1.address=t2.sql_address andt1.hash_value=t2.sql_hash_value
and t2.sid=t3.sid and t3.event='buffer busy waits';
3.获取等待的块的类型以及所在的segment,可以通过如下查询获得:
PHP code:
select 'Segment Header' class,a.segment_type,a.segment_name,a.partition_name from dba_segments a,v$session_wait b
where a.header_file=b.p1 and a.header_block=b.p2 and b.event='buffer busywaits'
union
select 'Freelist Groups'class,a.segment_type,a.segment_name,a.partition_name from dba_segments a,v$session_wait b
where a.header_file=b.p1 and b.p2 between a.header_block+1 and (a.header_block+a.freelist_groups) and a.freelist_groups>1 and b.event='buffer busy waits'
union
select a.segment_type||' block' class,a.segment_type,a.segment_name,a.partition_namefrom dba_extents a,v$session_wait b
where a.file_id=b.p1 and b.p2 between a.block_id and a.block_id+a.blocks-1 and b.event='buffer busywaits' and not exists(select 1 from dba_segments where
header_file=b.p1 and header_block=b.p2);
查询的第一部分:如果等待的块类型是segment header,那么可以直接拿buffer busy waits事件的p1和p2参数去dba_segments视图中匹配header_file和header_block字段即可找到等待的segment名称和segment类型,进行相应调整
查询的第二部分:如果等待的块类型是freelist groups,也可以在dba_segments视图中找出对应的segment名称和segment类型,注意这里的参数p2表示的freelist groups的位置是在segment的header_block+1到header_block+freelistgroups组数之间,并且freelist groups组数大于1
查询的第三部分:如果等待的块类型是普通的数据块,那么可以用p1、p2参数和dba_extents进行联合查询得到block所在的segment名称和segment类型
对于不同的等待块类型,我们采取不同的处理办法:
1.data segment header:
进程经常性的访问data segment header通常有两个原因:获取或修改process freelists信息、扩展高水位标记,针对第一种情况,进程频繁访问process freelists信息导致freelist争用,我们可以增大相应的segment对象的存储参数freelist或者freelist groups;若由于数据块频繁进出freelist而导致进程经常要修改freelist,则可以将pctfree值和pctused值设置较大的差距,从而避免数据块频繁进出freelist;对于第二种情况,由于该segment空间消耗很快,而设置的next extent过小,导致频繁扩展高水位标记,解决的办法是增大segment对象的存储参数next extent或者直接在创建表空间的时候设置extent size uniform
2.data block:
某一或某些数据块被多个进程同时读写,成为热点块,可以通过如下这些办法来解决这个问题:
(1)降低程序的并发度,如果程序中使用了parallel查询,降低parallel degree,以免多个parallel slave同时访问同样的数据对象而形成等待降低性能
(2)调整应用程序使之能读取较少的数据块就能获取所需的数据,减少buffer gets和physical reads
(3)减少同一个block中的记录数,使记录分布于更多的数据块中,这可以通过若干途径实现:可以调整segment对象的pctfree值,可以将segment重建到block size较小的表空间中,还可以用alter table minimizerecords_per_block语句减少每块中的记录数
(4)若热点块对象是类似自增id字段的索引,则可以将索引转换为反转索引,打散数据分布,分散热点块
3.undo segment header:
undo segment header争用是因为系统中undo segment不够,需要增加足够的undo segment,根据undo segment的管理方法,若是手工管理模式,需要修改rollback_segments初始化参数来增加rollback segment,若是自动管理模式,可以减小transactions_per_rollback_segment初始化参数的值来使oracle自动增多rollback segment的数量
4.undo block:
undo block争用是由于应用程序中存在对数据的读和写同时进行,读进程需要到undo segment中去获得一致性数据,解决办法是错开应用程序修改数据和大量查询数据的时间
小结:buffer busy waits事件是oracle等待事件中比较复杂的一个,其形成原因很多,需要根据p3参数对照Oracle提供的原因代码表进行相应的诊断,10g以后则需要根据等待的block类型结合引起等待时间的具体SQL进行分析,采取相应的调整措施
】
4) latch free:当闩锁丢失率高于0.5%时,需要调整这个问题。详细的我们在后面的Latch Activity for DB部分说明。
latch是一种低级排队机制,用于保护SGA中共享内存结构。latch就像是一种快速地被获取和释放的内存锁。用于防止共享内存结构被多个用户同时访问。如果latch不可用,就会记录latch释放失败(latch free miss )。有两种与闩有关的类型:
■ 立刻。
■ 可以等待。
假如一个进程试图在立刻模式下获得闩,而该闩已经被另外一个进程所持有,如果该闩不能立可用的话,那么该进程就不会为获得该闩而等待。它将继续执行另一个操作。
大多数latch问题都与以下操作相关:
没有很好的是用绑定变量(library cache latch)、重作生成问题(redo allocationlatch)、缓冲存储竞争问题(cache buffers LRU chain),以及buffer cache中的存在"热点"块(cache buffers chain)。
通常我们说,如果想设计一个失败的系统,不考虑绑定变量,这一个条件就够了,对于异构性强的系统,不使用绑定变量的后果是极其严重的。
另外也有一些latch等待与bug有关,应当关注Metalink相关bug的公布及补丁的发布。当latch miss ratios大于0.5%时,就应当研究这一问题。
Oracle的latch机制是竞争,其处理类似于网络里的CSMA/CD,所有用户进程争夺latch, 对于愿意等待类型(willing-to-wait)的latch,如果一个进程在第一次尝试中没有获得latch,那么它会等待并且再尝试一次,如果经过_spin_count次争夺不能获得latch, 然后该进程转入睡眠状态,持续一段指定长度的时间,然后再次醒来,按顺序重复以前的步骤.在8i/9i中默认值是_spin_count=2000。
如果SQL语句不能调整,在8.1.6版本以上,Oracle提供了一个新的初始化参数: CURSOR_SHARING可以通过设置CURSOR_SHARING = force在服务器端强制绑定变量。设置该参数可能会带来一定的副作用,对于Java的程序,有相关的bug,具体应用应该关注Metalink的bug公告。
***Latch 问题及可能解决办法
------------------------------
* Library Cache andShared Pool (未绑定变量---绑定变量,调整shared_pool_size)
每当执行SQL或PL/SQL存储过程,包,函数和触发器时,这个Latch即被用到.Parse操作中此Latch也会被频繁使用.
* Redo Copy (增大_LOG_SIMULTANEOUS_COPIES参数)
重做拷贝Latch用来从PGA向重做日志缓冲区拷贝重做记录.
* Redo Allocation (最小化REDO生成,避免不必要提交)
此Latch用来分配重做日志缓冲区中的空间,可以用NOLOGGING来减缓竞争.
* Row Cache Objects (增大共享池)
数据字典竞争.过度parsing.
* Cache Buffers Chains(_DB_BLOCK_HASH_BUCKETS应增大或设为质数)
"过热"数据块造成了内存缓冲链Latch竞争.
* Cache Buffers Lru Chain(调整SQL,设置DB_BLOCK_LRU_LATCHES,或使用多个缓冲区池)
扫描全部内存缓冲区块的LRU(最近最少使用)链时要用到内存缓冲区LRU链Latch.太小内存缓冲区、过大的内存缓冲区吞吐量、过多的内存中进行的排序操作、DBWR速度跟不上工作负载等会引起此Latch竞争。
5) Enqueue 队列是一种锁,保护一些共享资源,防止并发的DML操作。队列采用FIFO策略,注意latch并不是采用的FIFO机制。比较常见的有3种类型的队列:ST队列,HW队列,TX4队列。
ST Enqueue的等待主要是在字典管理的表空间中进行空间管理和分配时产生的。解决方法:1)将字典管理的表空间改为本地管理模式 2)预先分配分区或者将有问题的字典管理的表空间的next extent设置大一些。
HW Enqueue是用于segment的HWM的。当出现这种等待的时候,可以通过手工分配extents来解决。
TX4 Enqueue等待是最常见的等待情况。通常有3种情况会造成这种类型的等待:1)唯一索引中的重复索引。解决方法:commit或者rollback以释放队列。 2)对同一个位图索引段(bitmap index fragment)有多个update,因为一个bitmap index fragment可能包含了多个rowid,所以当多个用户更新时,可能一个用户会锁定该段,从而造成等待。解决方法同上。3)有多个用户同时对一个数据块作update,当然这些DML操作可能是针对这个数据块的不同的行,如果此时没有空闲的ITL槽,就会产生一个block-level锁。解决方法:增大表的initrans值使创建更多的ITL槽;或者增大表的pctfree值,这样oracle可以根据需要在pctfree的空间创建更多的ITL槽;使用smaller block size,这样每个块中包含行就比较少,可以减小冲突发生的机会。
AWR报告分析--等待事件-队列.doc
6) Free Buffer 释放缓冲区:这个等待事件表明系统正在等待内存中的可用空间,这说明当前Buffer中已经没有Free 的内存空间。如果应用设计良好,SQL 书写规范,充分绑定变量,那这种等待可能说明Buffer Cache 设置的偏小,你可能需要增大DB_CACHE_SIZE。该等待也可能说明DBWR 的写出速度不够,或者磁盘存在严重的竞争,可以需要考虑增加检查点、使用更多的DBWR进程,或者增加物理磁盘的数量,分散负载,平衡IO。
7) Log file single write:该事件仅与写日志文件头块相关,通常发生在增加新的组成员和增进序列号时。头块写单个进行,因为头块的部分信息是文件号,每个文件不同。更新日志文件头这个操作在后台完成,一般很少出现等待,无需太多关注。
8) log file parallel write:从log buffer写redo 记录到redo log 文件,主要指常规写操作(相对于log file sync)。如果你的Log group 存在多个组成员,当flush log buffer 时,写操作是并行的,这时候此等待事件可能出现。尽管这个写操作并行处理,直到所有I/O 操作完成该写操作才会完成(如果你的磁盘支持异步IO或者使用IO SLAVE,那么即使只有一个redo log file member,也有可能出现此等待)。这个参数和log file sync 时间相比较可以用来衡量log file 的写入成本。通常称为同步成本率。改善这个等待的方法是将redo logs放到I/O快的盘中,尽量不使用raid5,确保表空间不是处在热备模式下,确保redo log和data的数据文件位于不同的磁盘中。
9) log file sync:当一个用户提交或回滚数据时,LGWR将会话的redo记录从日志缓冲区填充到日志文件中,用户的进程必须等待这个填充工作完成。在每次提交时都出现,如果这个等待事件影响到数据库性能,那么就需要修改应用程序的提交频率, 为减少这个等待事件,须一次提交更多记录,或者将重做日志REDO LOG 文件访在不同的物理磁盘上,提高I/O的性能。
当一个用户提交或回滚数据时,LGWR 将会话期的重做由日志缓冲器写入到重做日志中。日志文件同步过程必须等待这一过程成功完成。为了减少这种等待事件,可以尝试一次提交更多的记录(频繁的提交会带来更多的系统开销)。将重做日志置于较快的磁盘上,或者交替使用不同物理磁盘上的重做日志,以降低归档对LGWR的影响。
对于软RAID,一般来说不要使用RAID 5,RAID5 对于频繁写入得系统会带来较大的性能损失,可以考虑使用文件系统直接输入/输出,或者使用裸设备(raw device),这样可以获得写入的性能提高。
10) log buffer space:日志缓冲区写的速度快于LGWR写REDOFILE的速度,可以增大日志文件大小,增加日志缓冲区的大小,或者使用更快的磁盘来写数据。
当你将日志缓冲(logbuffer)产生重做日志的速度比LGWR 的写出速度快,或者是当日志切换(log switch)太慢时,就会发生这种等待。这个等待出现时,通常表明redolog buffer 过小,为解决这个问题,可以考虑增大日志文件的大小,或者增加日志缓冲器的大小。
另外一个可能的原因是磁盘I/O 存在瓶颈,可以考虑使用写入速度更快的磁盘。在允许的条件下设置可以考虑使用裸设备来存放日志文件,提高写入效率。在一般的系统中,最低的标准是,不要把日志文件和数据文件存放在一起,因为通常日志文件只写不读,分离存放可以获得性能提升。
11) logfile switch:通常是因为归档速度不够快。表示所有的提交(commit)的请求都需要等待"日志文件切换"的完成。Log file Switch 主要包含两个子事件:
log file switch (archiving needed) 这个等待事件出现时通常是因为日志组循环写满以后,第一个日志归档尚未完成,出现该等待。出现该等待,可能表示io 存在问题。解决办法:①可以考虑增大日志文件和增加日志组;②移动归档文件到快速磁盘;③调整log_archive_max_processes。
log file switch (checkpoint incomplete) 当日志组都写完以后,LGWR 试图写第一个log file,如果这时数据库没有完成写出记录在第一个log file 中的dirty 块时(例如第一个检查点未完成),该等待事件出现。该等待事件通常表示你的DBWR 写出速度太慢或者IO 存在问题。为解决该问题,你可能需要考虑增加额外的DBWR 或者增加你的日志组或日志文件大小,或者也可以考虑增加checkpoint的频率。
12) DB File Parallel Write:文件被DBWR并行写时发生。解决办法:改善IO性能。
处理此事件时,需要注意
1)db fileparallel write事件只属于DBWR进程。
2)缓慢的DBWR可能影响前台进程。
3)大量的db fileparallel write等待时间很可能是I/O问题引起的。(在确认os支持异步io的前提下,你可以在系统中检查disk_asynch_io参数,保证为TRUE。可以通过设置db_writer_processes来提高DBWR进程数量,当然前提是不要超过cpu的数量。)
DBWR进程执行经过SGA的所有数据库写入,当开始写入时,DBWR进程编译一组脏块(dirty block),并且将系统写入调用发布到操作系统。DBWR进程查找在各个时间内写入的块,包括每隔3秒的一次查找,当前台进程提交以清除缓冲区中的内容时:在检查点处查找,当满足_DB_LARGE_DIRTY_QUEUE、_DB_BLOCK_MAX_DIRTY_TARGET和FAST_START_MTTR_TARGET阀值时,等等。
虽然用户会话从来没有经历过db file parallel write等待事件,但这并不意味着它们不会受到这种事件的影响。缓慢的DBWR写入性能可以造成前台会话在write complete waits或free buffer waits事件上等待。DBWR写入性能可能受到如下方面的影响:I/O操作的类型(同步或异步)、存储设备(裸设备或成熟的文件系统)、数据库布局和I/O子系统配置。需要查看的关键数据库统计是当db file parallel write、free buffer waits和writecomplete waits等待事件互相关联时,系统范围内的TIME_WAITED和AVERAGE_WAIT。
如果db file parallel write平均等待时间大于10cs(或者100ms),则通常表明缓慢的I/O吞吐量。可以通过很多方法来改善平均等待时间。主要的方法是使用正确类型的I/O操作。如果数据文件位于裸设备(raw device)上,并且平台支持异步I/O,就应该使用异步写入。但是,如果数据库位于文件系统上,则应该使用同步写入和直接I/O(这是操作系统直接I/O)。除了确保正在使用正确类型的I/O操作,还应该检查你的数据库布局并使用常见的命令监控来自操作系统的I/O吞吐量。例如sar -d或iostat -dxnC。
当db file parallel write平均等待时间高并且系统繁忙时,用户会话可能开始在free buffer waits事件上等待。这是因为DBWR进程不能满足释放缓冲区的需求。如果free buffer waits事件的TIME_WAITED高,则应该在高速缓存中增加缓冲区数量之前说明DBWR I/O吞吐量的问题。
高db file parallel write平均等待时间的另一个反响是在write complete waits等待事件上的高TIME_WAITED。前台进程不允许修改正在传输到磁盘的块。换句话说,也就是位于DBWR批量写入中的块。前台的会话在write complete waits等待事件上等待。因此,write complete waits事件的出现,一定标志着缓慢的DBWR进程,可以通过改进DBWR I/O吞吐量修正这种延迟。
13) DB File Single Write:当文件头或别的单独块被写入时发生,这一等待直到所有的I/O调用完成。解决办法:改善IO性能。
14) DB FILE Scattered Read:当扫描整个段来根据初始化参数db_file_multiblock_read_count读取多个块时发生,因为数据可能分散在不同的部分,这与分条或分段)相关,因此通常需要多个分散的读来读取所有的数据。等待时间是完成所有I/O调用的时间。解决办法:改善IO性能。
这种情况通常显示与全表扫描相关的等待。
当数据库进行全表扫时,基于性能的考虑,数据会分散(scattered)读入Buffer Cache。如果这个等待事件比较显著,可能说明对于某些全表扫描的表,没有创建索引或者没有创建合适的索引,我们可能需要检查这些数据表已确定是否进行了正确的设置。
然而这个等待事件不一定意味着性能低下,在某些条件下Oracle会主动使用全表扫描来替换索引扫描以提高性能,这和访问的数据量有关,在CBO下Oracle会进行更为智能的选择,在RBO下Oracle更倾向于使用索引。
因为全表扫描被置于LRU(Least Recently Used,最近最少适用)列表的冷端(cold end),对于频繁访问的较小的数据表,可以选择把他们Cache到内存中,以避免反复读取。
当这个等待事件比较显著时,可以结合v$session_longops动态性能视图来进行诊断,该视图中记录了长时间(运行时间超过6秒的)运行的事物,可能很多是全表扫描操作(不管怎样,这部分信息都是值得我们注意的)。
15) DB FILE Sequential Read:当前台进程对数据文件进行常规读时发生,包括索引查找和别的非整段扫描以及数据文件块丢弃等待。等待时间是完成所有I/O调用的时间。解决办法:改善IO性能。
如果这个等待事件比较显著,可能表示在多表连接中,表的连接顺序存在问题,没有正确地使用驱动表;或者可能索引的使用存在问题,并非索引总是最好的选择。在大多数情况下,通过索引可以更为快速地获取记录,所以对于编码规范、调整良好的数据库,这个等待事件很大通常是正常的。有时候这个等待过高和存储分布不连续、连续数据块中部分被缓存有关,特别对于DML频繁的数据表,数据以及存储空间的不连续可能导致过量的单块读,定期的数据整理和空间回收有时候是必须的。
需要注意在很多情况下,使用索引并不是最佳的选择,比如读取较大表中大量的数据,全表扫描可能会明显快于索引扫描,所以在开发中就应该注意,对于这样的查询应该进行避免使用索引扫描。
16) Direct Path Read:一般直接路径读取是指将数据块直接读入PGA中。一般用于排序、并行查询和read ahead操作。这个等待可能是由于I/O造成的。使用异步I/O模式或者限制排序在磁盘上,可能会降低这里的等待时间。
与直接读取相关联的等待事件。当ORACLE将数据块直接读入会话的PGA(进程全局区)中,同时绕过SGA(系统全局区)。PGA中的数据并不和其他的会话共享。即表明,读入的这部分数据该会话独自使用,不放于共享的SGA中。
在排序操作(order by/group by/union/distinct/rollup/合并连接)时,由于PGA中的SORT_AREA_SIZE空间不足,造成需要使用临时表空间来保存中间结果,当从临时表空间读入排序结果时,产生direct path read等待事件。
使用HASH连接的SQL语句,将不适合位于内存中的散列分区刷新到临时表空间中。为了查明匹配SQL谓词的行,临时表空间中的散列分区被读回到内存中(目的是为了查明匹配SQL谓词的行),ORALCE会话在direct path read等待事件上等待。
使用并行扫描的SQL语句也会影响系统范围的direct path read等待事件。在并行执行过程中,direct path read等待事件与从属查询有关,而与父查询无关,运行父查询的会话基本上会在PX Deq:Execute Reply上等待,从属查询会产生direct path read等待事件。
直接读取可能按照同步或异步的方式执行,取决于平台和初始化参数disk_asynch_io参数的值。使用异步I/O时,系统范围的等待的事件的统计可能不准确,会造成误导作用。
17) direct path write:直接路径写该等待发生在,系统等待确认所有未完成的异步I/O 都已写入磁盘。对于这一写入等待,我们应该找到I/O 操作最为频繁的数据文件(如果有过多的排序操作,很有可能就是临时文件),分散负载,加快其写入操作。如果系统存在过多的磁盘排序,会导致临时表空间操作频繁,对于这种情况,可以考虑使用Local管理表空间,分成多个小文件,写入不同磁盘或者裸设备。
在DSS系统中,存在大量的direct path read是很正常的,但是在OLTP系统中,通常显著的直接路径读(direct path read)都意味着系统应用存在问题,从而导致大量的磁盘排序读取操作。
直接路径写(direct paht write)通常发生在Oracle直接从PGA写数据到数据文件或临时文件,这个写操作可以绕过SGA。
这类写入操作通常在以下情况被使用:
·直接路径加载;
·并行DML操作;
·磁盘排序;
·对未缓存的“LOB”段的写入,随后会记录为direct path write(lob)等待。
最为常见的直接路径写,多数因为磁盘排序导致。对于这一写入等待,我们应该找到I/O操作最为频繁的数据文件(如果有过多的排序操作,很有可能就是临时文件),分散负载,加快其写入操作。
18) control file parallel write:当server 进程更新所有控制文件时,这个事件可能出现。如果等待很短,可以不用考虑。如果等待时间较长,检查存放控制文件的物理磁盘I/O 是否存在瓶颈。
多个控制文件是完全相同的拷贝,用于镜像以提高安全性。对于业务系统,多个控制文件应该存放在不同的磁盘上,一般来说三个是足够的,如果只有两个物理硬盘,那么两个控制文件也是可以接受的。在同一个磁盘上保存多个控制文件是不具备实际意义的。减少这个等待,可以考虑如下方法:①减少控制文件的个数(在确保安全的前提下)。②如果系统支持,使用异步IO。③转移控制文件到IO 负担轻的物理磁盘。
19) control file sequential read
control file single write :控制文件连续读/控制文件单个写对单个控制文件I/O存在问题时,这两个事件会出现。如果等待比较明显,检查单个控制文件,看存放位置是否存在I/O 瓶颈。
20) library cache pin
该事件通常是发生在先有会话在运行PL/SQL,VIEW,TYPES等object时,又有另外的会话执行重新编译这些object,即先给对象加上了一个共享锁,然后又给它加排它锁,这样在加排它锁的会话上就会出现这个等待。P1,P2可与x$kglpn和x$kglob表相关
X$KGLOB (Kernel Generic Library Cache Manager Object)
X$KGLPN (Kernel Generic Library Cache Manager Object Pins)
-- 查询X$KGLOB,可找到相关的object,其SQL语句如下
(即把V$SESSION_WAIT中的P1raw与X$KGLOB中的KGLHDADR相关连)
select kglnaown,kglnaobj from X$KGLOB
where KGLHDADR =(select p1raw from v$session_wait
where event='library cache pin')
-- 查出引起该等待事件的阻塞者的sid
select sid from x$kglpn , v$session
where KGLPNHDL in
(select p1raw from v$session_wait
where wait_time=0 and event like 'library cache pin%')
and KGLPNMOD <> 0
and v$session.saddr=x$kglpn.kglpnuse
-- 查出阻塞者正执行的SQL语句
select sid,sql_text
from v$session, v$sqlarea
where v$session.sql_address=v$sqlarea.address
and sid=<阻塞者的sid>
这样,就可找到"library cache pin"等待的根源,从而解决由此引起的性能问题。
21) library cache lock
该事件通常是由于执行多个DDL操作导致的,即在librarycache object上添加一个排它锁后,又从另一个会话给它添加一个排它锁,这样在第二个会话就会生成等待。可通过到基表x$kgllk中查找其对应的对象。
-- 查询引起该等待事件的阻塞者的sid、会话用户、锁住的对象
select b.sid,a.user_name,a.kglnaobj
from x$kgllk a , v$session b
where a.kgllkhdl in
(select p1raw from v$session_wait
where wait_time=0 and event = 'library cache lock')
and a.kgllkmod <> 0
and b.saddr=a.kgllkuse
当然也可以直接从v$locked_objects中查看,但没有上面语句直观根据sid可以到v$process中查出pid,然后将其kill或者其它处理。
22)
对于常见的一些IDLE wait事件举例:
dispatcher timer
lock element cleanup
Null event
parallel query dequeuewait
parallel query idle wait -Slaves
pipe get
PL/SQL lock timer
pmon timer- pmon
rdbms ipc message
slave wait
smon timer
SQL*Net break/reset toclient
SQL*Net message fromclient
SQL*Net message toclient
SQL*Net more data toclient
virtual circuit status
client message
SQL*Net message fromclient
下面是关于这里的常见的等待事件和解决方法的一个快速预览
等待事件 |
一般解决方法 |
Sequential Read |
调整相关的索引和选择合适的驱动行源 |
Scattered Read |
表明出现很多全表扫描。优化code,cache小表到内存中。 |
Free Buffer |
增大DB_CACHE_SIZE,增大checkpoint的频率,优化代码 |
Buffer Busy Segment header |
增加freelist或者freelistgroups |
Buffer Busy Data block |
隔离热块;使用反转索引;使用更小的块;增大表的initrans |
Buffer Busy Undo header |
增加回滚段的数量或者大小 |
Buffer Busy Undo block |
Commit more;增加回滚段的数量或者大小 |
Latch Free |
检查具体的等待latch类型,解决方法参考后面介绍 |
Enqueue–ST |
使用本地管理的表空间或者增加预分配的盘区大小 |
Enqueue–HW |
在HWM之上预先分配盘区 |
Enqueue–TX4 |
在表或者索引上增大initrans的值或者使用更小的块 |
Log Buffer Space |
增大LOG_BUFFER,改善I/O |
Log File Switch |
增加或者增大日志文件 |
Log file sync |
减小提交的频率;使用更快的I/O;或者使用裸设备 |
Write complete waits |
增加DBWR;提高CKPT的频率; |
Time Model Statistics
- Total time in database user-calls (DB Time): 663s
- Statistics including the word "background" measure background process time, and so do not contribute to the DB time statistic
- Ordered by % or DB time desc, Statistic name
Statistic Name |
Time (s) |
% of DB Time |
DB CPU |
514.50 |
77.61 |
sql execute elapsed time |
482.27 |
72.74 |
parse time elapsed |
3.76 |
0.57 |
PL/SQL execution elapsed time |
0.50 |
0.08 |
hard parse elapsed time |
0.34 |
0.05 |
connection management call elapsed time |
0.08 |
0.01 |
hard parse (sharing criteria) elapsed time |
0.00 |
0.00 |
repeated bind elapsed time |
0.00 |
0.00 |
PL/SQL compilation elapsed time |
0.00 |
0.00 |
failed parse elapsed time |
0.00 |
0.00 |
DB time |
662.97 |
|
background elapsed time |
185.19 |
|
background cpu time |
67.48 |
|
此节显示了各种类型的数据库处理任务所占用的CPU时间。
DB time=报表头部显示的db time=cpu time + all of nonidle wait event time
Back toWait Events Statistics
Back to Top
Wait Class 等待事件的类型
- s - second
- cs - centisecond - 100th of a second
- ms - millisecond - 1000th of a second
- us - microsecond - 1000000th of a second
- ordered by wait time desc, waits desc
查询Oracle 10gR1提供的12个等待事件类:
select wait_class#,wait_class_id, wait_class from v$event_name group by wait_class#, wait_class_id,wait_class order by wait_class#;
Wait Class |
Waits |
%Time -outs |
Total Wait Time (s) |
Avg wait (ms) |
Waits /txn |
User I/O |
66,837 |
0.00 |
120 |
2 |
11.94 |
System I/O |
28,295 |
0.00 |
93 |
3 |
5.05 |
Network |
1,571,450 |
0.00 |
66 |
0 |
280.72 |
Cluster |
210,548 |
0.00 |
29 |
0 |
37.61 |
Other |
81,783 |
71.82 |
28 |
0 |
14.61 |
Application |
333,155 |
0.00 |
16 |
0 |
59.51 |
Concurrency |
5,182 |
0.04 |
5 |
1 |
0.93 |
Commit |
919 |
0.00 |
4 |
4 |
0.16 |
Configuration |
25,427 |
99.46 |
1 |
0 |
4.54 |
Back toWait Events Statistics
Back to Top
Wait Events 现实非空闲等待事件后面是空闲等待事件
- s - second
- cs - centisecond - 100th of a second
- ms - millisecond - 1000th of a second
- us - microsecond - 1000000th of a second
- ordered by wait time desc, waits desc (idle events last)
(1)查询所有等待事件及其属性:
select event#, name, parameter1, parameter2, parameter3from v$event_name order by name;
(2)查询Oracle 10gR1提供的12个等待事件类:
select wait_class#,wait_class_id, wait_class from v$event_name group by wait_class#,wait_class_id, wait_class order by wait_class#;
wait_event.doc
下面显示的内容可能来自下面几个视图)
V$EVENT_NAME视图包含所有为数据库实例定义的等待事件。
V$SYSTEM_EVENT视图显示自从实例启动后,所有Oracle会话遇到的所有等待事件的总计统计。
V$SESSION_EVENT视图包含当前连接到实例的所有会话的总计等待事件统计。该视图包含了V$SYSTEM_EVENT视图中出现的所有列。它记录会话中每一个等待事件的总等待次数、已等待时间和最大等待时间。SID列标识出独立的会话。每个会话中每个事件的最大等待时间在MAX_WAIT列中追踪。通过用SID列将V$SESSION_EVENT视图和V$SESSION视图结合起来,可得到有关会话和用户的更多信息。
V$SESSION_WAIT视图提供关于每个会话正在等待的事件或资源的详细信息。该视图在任何给定时间,只包含每个会话的一行活动的或不活动的信息。
自从OWI在Oracle 7.0.12中引入后,就具有下来4个V$视图:
· V$EVENT_NAME
· V$SESSION_WAIT
· V$SESSION_EVENT
· V$SYSTEM_EVENT
除了这些等待事件视图之外,Oracle 10gR1中引入了下列新视图以从多个角度显示等待信息:
· V$SYSTEM_WAIT_CLASS
· V$SESSION_WAIT_CLASS
· V$SESSION_WAIT_HISTORY
· V$EVENT_HISTOGRAM
· V$ACTIVE_SESSION_HISTORY
然而,V$SESSION_WAIT、V$SESSION_WAIT和V$SESSION_WAIT仍然是3个重要的视图,它们提供了不同粒度级的等待事件统计和计时信息。三者的关系如下:
V$SESSION_WAIT Ì V$SESSION_EVENT ÌV$SYSTEM_EVENT
Event |
Waits |
%Time -outs |
Total Wait Time (s) |
Avg wait (ms) |
Waits /txn |
SQL*Net more data from client |
27,319 |
0.00 |
64 |
2 |
4.88 |
log file parallel write |
5,497 |
0.00 |
47 |
9 |
0.98 |
db file sequential read |
7,900 |
0.00 |
35 |
4 |
1.41 |
db file parallel write |
4,806 |
0.00 |
34 |
7 |
0.86 |
db file scattered read |
10,310 |
0.00 |
31 |
3 |
1.84 |
direct path write |
42,724 |
0.00 |
30 |
1 |
7.63 |
reliable message |
355 |
2.82 |
18 |
49 |
0.06 |
SQL*Net break/reset to client |
333,084 |
0.00 |
16 |
0 |
59.50 |
db file parallel read |
3,732 |
0.00 |
13 |
4 |
0.67 |
gc current multi block request |
175,710 |
0.00 |
10 |
0 |
31.39 |
control file sequential read |
15,974 |
0.00 |
10 |
1 |
2.85 |
direct path read temp |
1,873 |
0.00 |
9 |
5 |
0.33 |
gc cr multi block request |
20,877 |
0.00 |
8 |
0 |
3.73 |
log file sync |
919 |
0.00 |
4 |
4 |
0.16 |
gc cr block busy |
526 |
0.00 |
3 |
6 |
0.09 |
enq: FB - contention |
10,384 |
0.00 |
3 |
0 |
1.85 |
DFS lock handle |
3,517 |
0.00 |
3 |
1 |
0.63 |
control file parallel write |
1,946 |
0.00 |
3 |
1 |
0.35 |
gc current block 2-way |
4,165 |
0.00 |
2 |
0 |
0.74 |
library cache lock |
432 |
0.00 |
2 |
4 |
0.08 |
name-service call wait |
22 |
0.00 |
2 |
76 |
0.00 |
row cache lock |
3,894 |
0.00 |
2 |
0 |
0.70 |
gcs log flush sync |
1,259 |
42.02 |
2 |
1 |
0.22 |
os thread startup |
18 |
5.56 |
2 |
89 |
0.00 |
gc cr block 2-way |
3,671 |
0.00 |
2 |
0 |
0.66 |
gc current block busy |
113 |
0.00 |
1 |
12 |
0.02 |
SQL*Net message to client |
1,544,115 |
0.00 |
1 |
0 |
275.83 |
gc buffer busy |
15 |
6.67 |
1 |
70 |
0.00 |
gc cr disk read |
3,272 |
0.00 |
1 |
0 |
0.58 |
direct path write temp |
159 |
0.00 |
1 |
5 |
0.03 |
gc current grant busy |
898 |
0.00 |
1 |
1 |
0.16 |
log file switch completion |
29 |
0.00 |
1 |
17 |
0.01 |
CGS wait for IPC msg |
48,739 |
99.87 |
0 |
0 |
8.71 |
gc current grant 2-way |
1,142 |
0.00 |
0 |
0 |
0.20 |
kjbdrmcvtq lmon drm quiesce: ping completion |
9 |
0.00 |
0 |
19 |
0.00 |
enq: US - contention |
567 |
0.00 |
0 |
0 |
0.10 |
direct path read |
138 |
0.00 |
0 |
1 |
0.02 |
enq: WF - contention |
14 |
0.00 |
0 |
9 |
0.00 |
ksxr poll remote instances |
13,291 |
58.45 |
0 |
0 |
2.37 |
library cache pin |
211 |
0.00 |
0 |
1 |
0.04 |
ges global resource directory to be frozen |
9 |
100.00 |
0 |
10 |
0.00 |
wait for scn ack |
583 |
0.00 |
0 |
0 |
0.10 |
log file sequential read |
36 |