常见等待事件说明
Oracle的等待事件是衡量Oracle运行状况的重要依据及指标。
等待事件的概念是在Oracle7.0.1.2中引入的,大致有100个等待事件。在Oracle 8.0中这个数目增加到了大约150个,在Oracle8i中大约有200个事件,在Oracle9i中大约有360个等待事件。主要有两种类别的等待事件,即空闲(idle)等待事件和非空闲(non-idle)等待事件。
空闲事件指Oracle正等待某种工作,在诊断和优化数据库的时候,我们不用过多注意这部分事件。常见的空闲事件有:
dispatcher timer
lock element cleanup
Null event
parallel query dequeue wait
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 to client
SQL*Net message from client
SQL*Net message to client
SQL*Net more data to client
virtual circuit status
client message
非空闲等待事件专门针对Oracle的活动,指数据库任务或应用运行过程中发生的等待,这些等待事件是我们在调整数据库的时候应该关注与研究的。一些常见的非空闲等待事件有:
db file scattered read
db file sequential read
buffer busy waits
free buffer waits
enqueue
latch free
log file parallel write
log file sync
1、db file scattered read-DB 文件分散读取
这种情况通常显示与全表扫描相关的等待。
当数据库进行全表扫时,基于性能的考虑,数据会分散(scattered)读入 Buffer Cache。如果这个等待事件比较显著,可能说明对于某些全表扫描的表,没有创建索引或者没有创建合适的索引,我们可能需要检查这些数据表已确定是否进行了正确的设置。
然而这个等待事件不一定意味着性能低下,在某些条件下 Oracle 会主动使用全表扫描来替换索引扫描以提高性能,这和访问的数据量有关,在 CBO 下 Oracle 会进行更为智能的选择,在RBO下Oracle更倾向于使用索引。因为全表扫描被置于 LRU(Least Recently Used,最近最少适用)列表的冷端(cold end),对于频繁访问的较小的数据表,可以选择把他们 Cache 到内存中,以避免反复读取。
当这个等待事件比较显著时,可以结合 v$session_longops 动态性能视图来进行诊断,该视图中记录了长时间(运行时间超过 6 秒的)运行的事物,可能很多是全表扫描操作(不管怎样,这部分信息都是值得我们注意的)。
我们通过通过一个案例分析来熟悉一下这个等待事件:
DB Name DB Id Instance Inst Num Release Cluster Host
------------ ----------- ------------ -------- ----------- ------- ------------
K2 1999167370 k2 1 8.1.5.0.0 NO K2
Snap Id Snap Time Sessions Curs/Sess Comment
------- ------------------ -------- --------- -------------------
Begin Snap: 170 25-Feb-03 10:00:11 12 4.5
End Snap: 176 25-Feb-03 15:00:05 12 5.0
Elapsed: 299.90 (mins)
Cache Sizes (end)
~~~~~~~~~~~~~~~~~
Buffer Cache: 24M Std Block Size: 8K
Shared Pool Size: 157M Log Buffer: 8388K
………………
Top 5 Timed Events
~~~~~~~~~~~~~~~~~~ % Total
Event Waits Time (s) Ela Time
-------------------------------------------- ------------ ----------- --------
db file scattered read 16,842,920 3,490,719 43.32
latch free 844,272 3,270,073 40.58
buffer busy waits 114,421 933,136 11.58
db file sequential read 2,067,910 117,750 1.46
enqueue 464 110,840 1.38
-------------------------------------------------------------
这是一个典型的性能低下的系统,几个重要的等待事件都在 Top 5 中出现,其中,前 3 个等待极为显著,需要进行相应的调整。
在 5 小时的采样间隔内,其中 db file scattered read 累计等待时间约 10 小时,已经成为影响系统性能的主要原因。了解了这些以后我们就可以进一步察看相关 SQL 看是否存在可以的 SQL 语句。
SQL ordered by Gets for DB: K2 Instance: k2 Snaps: 170 -176
-> End Buffer Gets Threshold: 10000
-> Note that resources reported for PL/SQL includes the resources used by
all SQL statements called within the PL/SQL code. As individual SQL
statements are also reported, it is possible and valid for the summed
total % to exceed 100
CPU Elapsd
Buffer Gets Executions Gets per Exec %Total Time (s) Time (s) Hash Value
--------------- ------------ -------------- ------ -------- --------- ----------
6,480,163 12 540,013.6 2.4 0.00 0.00 3791855498
SELECT "PROCESS_REQ"."WORK_ID", "PROCESS_REQ"."STOCK_NO","PROCESS_R
3,784,566 16 236,535.4 1.4 0.00 0.00 2932917818
SELECT * FROM FIND_LATER_WO ORDER BY NOTE,ORDER_NO
1,200,976 3 400,325.3 .4 0.00 0.00 4122791109
SELECT "ITEM_STOCK"."ITEM_NO","ITEM"."NOTE", "ITEM"
923,944 9 102,660.4 .3 0.00 0.00 2200071737
SELECT "ITEM_STOCK"."ITEM_NO" , "ITEM_STOCK"."STOCK_NO" ,
921,301 3 307,100.3 .3 0.00 0.00 2218843294
SELECT "ITEM_STOCK"."ITEM_NO", "ITEM"."NOTE", "ITEM"
………………
注意到以上很多查询导致的 Buffer Gets 都非常庞大,我们非常有理由怀疑索引存在问题,甚至缺少必要的索引。以上记录的是 SQL 的片段,通过 Hash Value 值结合 v$sql_text 我们可以获得完整的 SQL语句。
在这次诊断中,我紧接着去查询的是 v$session_longops 数据表,一个分组查询的结果如下:
TARGET COUNT(*)
----------------------------------------- ----------
SA.PPBT_GRAPHOBJTABLE 418
SA.PPBT_PPBTOBJRELATTABLE 53
我们发现这些问题 SQL 的全表扫描(结合 v$session_longops 视图中的 OPNAME)主要集中在 PPBT_GRAPHOBJTABLE 和 PPBT_PPBTOBJRELATTABLE 两张数据表上。进一步研究发现这两个数据表上没有任何索引,并且有相当的数据量:
SQL> select count(*) from SA.PPBT_PPBTOBJRELATTABLE;
COUNT(*)
----------
1209017
SQL> select count(*) from SA.PPBT_GRAPHOBJTABLE;
COUNT(*)
----------
2445
在创建了合适的索引后,系统性能得到了大幅提高!
2、db file sequential read-DB 文件顺序读取
这一事件通常显示与单个数据块相关的读取操作(如索引读取)。
如果这个等待事件比较显著,可能表示在多表连接中,表的连接顺序存在问题,可能没有正确的使用驱动表;或者可能说明不加选择地进行索引。
在大多数情况下我们说,通过索引可以更为快速的获取记录,所以对于一个编码规范、调整良
好的数据库,这个等待很大是很正常的。
但是在很多情况下,使用索引并不是最佳的选择,比如读取较大表中大量的数据,全表扫描可
能会明显快于索引扫描,所以在开发中我们就应该注意,对于这样的查询应该进行避免使用索引扫描。
3、Free Buffer-释放缓冲区
这个等待事件表明系统正在等待内存中的可用空间,这说明当前 Buffer 中已经没有 Free 的内存空间。
如果应用设计良好,SQL 书写规范,充分绑定变量,那这种等待可能说明 Buffer Cache 设置的偏小,你可能需要增大 DB_BUFFER_CACHE。
Free Buffer 等待可能说明 DBWR 的写出速度不够,或者磁盘存在严重的竞争,可以需要考虑增加检查点、使用更多的 DBWR 进程,或者增加物理磁盘的数量,分散负载,平衡 IO。
4、Buffer Busy-缓冲区忙
该等待事件表示正在等待一个以unshareable方式使用的缓冲区,或者表示当前正在被读入buffer cache。一般来说Buffer Busy Wait不应大于1%。
检查缓冲等待统计部分(或V$WAITSTAT),看一下等待是否位于段头(Segment Header)。如果是,可以考虑增加自由列表(freelist,对于Oracle8i DMT)或者增加freelist groups(在很多时候这个调整是立竿见影的,在8.1.6之前,这个freelists参数不能动态修改;在8.1.6及以后版本,动态修改feelists需要设置COMPATIBLE至少为8.1.6).
其修改语法为:
SQL> alter table sp_item storage (freelists 2);
表已更改。
如果这一等待位于undo header,可以通过增加回滚段(rollback segment)来解决缓冲区的问题。如果等待位于undo block上,我们可能需要检查相关应用,适当减少大规模的一致性读取,或者降低一致性读取(consistent read)的表中的数据密度或者增大DB_CACHE_SIZE。
如果等待处于data block,可以考虑将频繁并发访问的表或数据移到另一数据块或者进行更大范围的分布(可以增加pctfree值 ,扩大数据分布,减少竞争),以避开这个"热点"数据块,或者可以考虑增加表中的自由列表或使用本地化管理的表空间(Locally Managed Tablespaces)。
如果等待处于索引块,应该考虑重建索引、分割索引或使用反向键索引。为了防止与数据块相关的缓冲忙等待,也可以使用较小的块:在这种情况下,单个块中的记录就较少,所以这个块就不是那么"繁忙";或者可以设置更大的pctfree,使数据扩大物理分布,减少记录间的热点竞争。
在执行DML (insert/update/ delete)时,Oracle向数据块中写入信息,对于多事务并发访问的数据表,关于ITL的竞争和等待可能出现,为了减少这个等待,可以增加initrans,使用多个ITL槽。以下是一个生产系统v$waitstat试图所显示的等待信息:
SQL> select * from v$waitstat where count<>0 or time <>0;
CLASS COUNT TIME
--------------------- -------------
data block 453 6686
undo header 391 1126
undo block 172 3
在 Oracle9i 中,引入了一个新概念:ASSM(Segment Space Management Auto)。通过这个新特性 Oracle 使用位图来管理空间使用。 ASSM 结合 LMT 彻底改变了 Oracle 的存储机制,位图 freelist 能够减轻缓冲区忙等待(buffer busy wait),这个问题在 Oracle9i 以前的版本里曾是一个严重的问题。
Oracle 宣称 ASSM 显著地提高了 DML 并发操作的性能,因为(同一个)位图的不同部分可以被同时使用,这样就消除了寻找剩余空间的串行化。根据 Oracle 的测试结果,使用位图 freelist 会消除所有分段头部(对资源)的争夺,还能获得超快的并发插入操作在 Oracle9i 之中,Buffer Busy wait 不再常见!
5、latch free-latch 释放
latch是一种低级排队机制,用于保护SGA中共享内存结构。
latch就像是一种快速地被获取和释放的内存锁。用于防止共享内存结构被多个用户同时访问。如果latch不可用,就会记录latch释放失败(latch free miss )。
有两种与闩有关的类型:
■ 立刻。
■ 可以等待。
假如一个进程试图在立刻模式下获得闩,而该闩已经被另外一个进程所持有,如果该闩不能立可用的话,那么该进程就不会为获得该闩而等待。它将继续执行另一个操作。
大多数latch问题都与以下操作相关:
没有很好的是用绑定变量(library cache latch)、重作生成问题(redo allocation latch)、缓冲存储竞争问题(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公告。
以下我们简单来看一下对栓的查询及跟踪:
SQL> select addr,name
2 from v$latch_children
3 where name like '%chain%'
4 /
ADDR NAME
---------------- ------------------------------
00000003C0558AE8 enqueue hash chains
00000003C0558A58 enqueue hash chains
00000003C05589C8 enqueue hash chains
00000003C0558938 enqueue hash chains
00000003C05588A8 enqueue hash chains
00000003C0558818 enqueue hash chains
00000003C0558788 enqueue hash chains
00000003C05586F8 enqueue hash chains
00000003C1FC7830 cache buffers lru chain
00000003C1FC7448 cache buffers lru chain
00000003C1FC7060 cache buffers lru chain
00000003C1FC6C78 cache buffers lru chain
00000003C247D970 cache buffers chains
00000003C247C8C0 cache buffers chains
00000003C247B810 cache buffers chains
00000003C247A760 cache buffers chains
00000003C24796B0 cache buffers chains
00000003C2478600 cache buffers chains
00000003C2477550 cache buffers chains
00000003C24764A0 cache buffers chains
00000003C24753F0 cache buffers chains
00000003C2474340 cache buffers chains
………
SQL> col segment_name for a40
SQL> set linesize 120
SQL> l
1 select /*+ ordered */
2 e.owner ||'.'|| e.segment_name segment_name,
3 e.extent_id extent#,
4 x.dbablk - e.block_id + 1 block#,
5 x.tch,
6 l.child#
7 from
8 sys.v$latch_children l,
9 sys.x$bh x,
10 sys.dba_extents e
11 where
12 l.name = 'cache buffers chains' and
13 l.sleeps > &sleep_count and
14 x.hladdr = l.addr and
15 e.file_id = x.file# and
16 x.dbablk between e.block_id and e.block_id + e.blocks - 1
17 /
Enter value for sleep_count: 10000
old 13: l.sleeps > &sleep_count and
new 13: l.sleeps > 10000 and
SEGMENT_NAME EXTENT# BLOCK# TCH CHILD#
---------------------------------------- ---------- ---------- ---------- ----------
SYS.I_ACCESS1 14 16 12 1001
SYS.I_DEPENDENCY2 2 11 25 804
SYS.I_DEPENDENCY2 2 13 23 806
SYS.I_DEPENDENCY1 2 10 1 1019
SYS.I_DEPENDENCY1 2 11 2 1020
…………
HSCONTENT.HSIDX_INFO_PARAM 50 2 35635 1017
HSCONTENT.HSIDX_INFO_PARAM 50 3 51269 1018
HSCONTENT.HSIDX_INFO_PARAM 50 4 32415 1019
HSCONTENT.HSIDX_INFO_PARAM 50 5 51956 1020
HSCONTENT.HSIDX_INFO_PARAM 50 6 57509 1021
HSCONTENT.PK_HS_DLF_OBJECT 11 2 4434 809
HSCONTENT.PK_HS_DLF_OBJECT 11 6 5738 813
HSCONTENT.PK_HS_DLF_OBJECT 14 2 524 1001
HSCONTENT.PK_HS_DLF_OBJECT 23 2 4843 1001
HSCONTENT.PK_HS_DLF_OBJECT 24 2 4361 1001
HSCONTENT.PK_HS_DLF_OBJECT 25 13 2507 804
…………
6、Enqueue
enqueue是一种保护共享资源的锁定机制。该锁定机制保护共享资源,如记录中的数据,以避免两个人在同一时间更新同一数据。enqueue包括一个排队机制,即FIFO(先进先出)排队机制。
Enqueue等待常见的有ST、HW 、TX 、TM等
ST enqueue,用于空间管理和字典管理的表空间(DMT)的区间分配,在DMT中典型的是对于uet$ 和fet$数据字典表的争用。对于支持LMT的版本,应该尽量使用本地管理表空间. 或者考虑手工预分配一定数量的区(Extent),减少动态扩展时发生的严重队列竞争。
我们通过一个实例来看一下:
DB Name DB Id Instance Inst Num Release Cluster Host
------------ ----------- ------------ -------- ----------- ------- ------------
DB 407573460 aaa 1 8.1.7.4.0 NO server
Snap Id Snap Time Sessions Curs/Sess Comment
------- ------------------- -------- --------- -------------------
Begin Snap: 2845 31-10月-03 02:10:16 46 4.5
End Snap: 2848 31-10月-03 03:40:05 46 5.0
Elapsed: 89.82 (mins)
Cache Sizes (end)
~~~~~~~~~~~~~~~~~
Buffer Cache: 51M Std Block Size: 16K
Shared Pool Size: 209M Log Buffer: 2097K
………………
Top 5 Timed Events
~~~~~~~~~~~~~~~~~~ % Total
Event Waits Time (s) Ela Time
-------------------------------------------- ------------ ----------- --------
enqueue 53,793 16,192,686 67.86
rdbms ipc message 19,999 5,927,350 24.84
pmon timer 1,754 538,797 2.26
smon timer 17 522,281 2.19
SQL*Net message from client 94,525 520,104 2.18
-------------------------------------------------------------
在Statspack分析中,Top 5等待事件是我们最为关注的部分。
这个系统中,除了enqueue 等待事件以外,其他4个都属于空闲等待事件,无须关注。我们来关注一下enqueue 等待事件,在89.82 (mins)的采样间隔内,累计enqueue等待长达16,192,686cs,即45小时左右。这个等待已经太过显著,实际上这个系统也正因此遭遇了巨大的困难,观察到队列等待以后,我们就应该关注队列等待在等待什么资源。快速跳转的Statspack的其他部分,我们看到以下详细内容:
Enqueue activity for DB: DB Instance: aaa Snaps: 2716 -2718
-> ordered by waits desc, gets desc
Enqueue Gets Waits
---------- ------------ ----------
ST 1,554 1,554
-------------------------------------------------------------
我们看到主要队列等待在等待ST锁定,对于DMT,我们说这个等待跟FET$,UET$的争用紧密相关。我们在回过头来研究捕获的SQL语句:
-> End Buffer Gets Threshold: 10000
-> Note that resources reported for PL/SQL includes the resources used by
all SQL statements called within the PL/SQL code. As individual SQL
statements are also reported, it is possible and valid for the summed
total % to exceed 100
Buffer Gets Executions Gets per Exec %Total Hash Value
--------------- ------------ -------------- ------ ----------
4,800,073 10,268 467.5 51.0 2913840444
select length from fet$ where file#=:1 and block#=:2 and ts#=:3
803,187 10,223 78.6 8.5 528349613
delete from uet$ where ts#=:1 and segfile#=:2 and segblock#=:3 and ext#=:4
454,444 10,300 44.1 4.8 1839874543
select file#,block#,length from uet$ where ts#=:1 and segfile#=:2 and segblock#=:3 and ext#=:4
23,110 10,230 2.3 0.2 3230982141
insert into fet$ (file#,block#,ts#,length) values (:1,:2,:3,:4)
21,201 347 61.1 0.2 1705880752
select file# from file$ where ts#=:1
…………
9,505 12 792.1 0.1 1714733582
select f.file#, f.block#, f.ts#, f.length from fet$ f, ts$ t where t.ts#=f.ts# and t.dflextpct!=0 and t.bitmapped=0
6,426 235 27.3 0.1 1877781575
delete from fet$ where file#=:1 and block#=:2 and ts#=:3
我们看到数据库频繁操作UET$,FET$系统表已经成为了系统的主要瓶颈。至此,我们已经可以准确的为该系统定位问题,相应的解决方案也很容易确定,在8.1.7中,使用LMT代替DMT,这是解决问题的根本办法,当然实施起来还要进行综合考虑,实际情况还要复杂得多。
HW enqueue指和段的高水位标记相关等待;手动分配适当区可以避免这一等待。
TX是最常见的enqueue等待。TX enqueue等待通常是以下三个问题之一产生的结果。
第一个问题是唯一索引中的重复索引,你需要执行提交(commit)/回滚(rollback)操作来释放 enqueue。
第二个问题是对同一位图索引段的多次更新。因为单个位图段可能包含多个行地址(rowid),所以当多个用户试图更新同一段时,可能一个用户会锁定其他用户请求的记录,这时等待出现。直到获得锁定的用户提交或回滚, enqueue释放。
第三个问题,也是最可能发生的问题是多个用户同时更新同一个块。如果没有足够的ITL槽,就会发生块级锁定。通过增大initrans和/或maxtrans以允许使用多个ITL槽(对于频繁并发进行DML操作的数据表,在建表之初就应该考虑为相应参数设置合理的数值,避免系统运行以后在线的更改,在8i之前,freelists等参数不能在线更改,设计时的考虑就尤为重要),或者增大表上的pctfree值,就可以很容易的避免这种情况。
TM enqueue队列锁在进行DML操作前获得,以阻止对正在操作的数据表进行任何DDL操作(在DML操作一个数据表时,其结构不能被更改)。
7、Log Buffer Space-日志缓冲空间
当你将日志缓冲(log buffer)产生重做日志的速度比 LGWR 的写出速度快,或者是当日志切换(log switch)太慢时,就会发生这种等待。这个等待出现时,通常表明 redo log buffer 过小,为解决这个问题,可以考虑增大日志文件的大小,或者增加日志缓冲器的大小。
另外一个可能的原因是磁盘 I/O 存在瓶颈,可以考虑使用写入速度更快的磁盘。在允许的条件下设置可以考虑使用裸设备来存放日志文件,提高写入效率。在一般的系统中,最低的标准是,不要把日志文件和数据文件存放在一起,因为通常日志文件只写不读,分离存放可以获得性能提升。
以下是一个 log buffer 存在问题的 statspack Top5 等待事件的系统:
Top 5 Wait Events
~~~~~~~~~~~~~~~ Wait % Total
Event Waits Time (cs) Wt Time
-------------------------------------------- ------------ ------------ -------
log file parallel write 1,436,993 1,102,188 10.80
log buffer space 16,698 873,203 8.56
log file sync 1,413,374 654,587 6.42
control file parallel write 329,777 510,078 5.00
db file scattered read 425,578 132,537 1.30
-------------------------------------------------------------
8、Log File Switch-日志文件切换
当这个等待出现时,表示所有的提交(commit)的请求都需要等待"日志文件切换"的完成。
Log file Switch 主要包含两个子事件:
log file switch (archiving needed)
log file switch (checkpoint incomplete)
log file switch (archiving needed)
这个等待事件出现时通常是因为日志组循环写满以后,第一个日志归档尚未完成,出现该等待。出现该等待,可能表示 io 存在问题。
解决办法:
可以考虑增大日志文件和增加日志组
移动归档文件到快速磁盘
调整 log_archive_max_processes .
log file switch (checkpoint incomplete)-日志切换(检查点未完成)
当你的日志组都写完以后,LGWR 试图写第一个 log file,如果这时数据库没有完成写出记录在第一个 log file 中的 dirty 块时(例如第一个检查点未完成),该等待事件出现。该等待事件通常表示你的 DBWR 写出速度太慢或者 IO 存在问题。为解决该问题,你可能需要考虑增加额外的 DBWR 或者增加你的日志组或日志文件大小。
9、log file sync-日志文件同步
当一个用户提交或回滚数据时,LGWR 将会话期的重做由日志缓冲器写入到重做日志中。日志文件同步过程必须等待这一过程成功完成。
为了减少这种等待事件,可以尝试一次提交更多的记录(频繁的提交会带来更多的系统开销)。将重做日志置于较快的磁盘上,或者交替使用不同物理磁盘上的重做日志,以降低归档对 LGWR的影响。
对于软 RAID,一般来说不要使用 RAID 5,RAID5 对于频繁写入得系统会带来较大的性能损失,可以考虑使用文件系统直接输入/输出,或者使用裸设备(raw device),这样可以获得写入的性能提高。
10、log file single write
该事件仅与写日志文件头块相关,通常发生在增加新的组成员和增进序列号时。头块写单个进行,因为头块的部分信息是文件号,每个文件不同。更新日志文件头这个操作在后台完成,一般很少出现等待,无需太多关注。
11、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 的写入成本。通常称为同步成本率。
12、control file parallel write-控制文件并行写
当 server 进程更新所有控制文件时,这个事件可能出现。如果等待很短,可以不用考虑。如果等待时间较长,检查存放控制文件的物理磁盘 I/O 是否存在瓶颈。
多个控制文件是完全相同的拷贝,用于镜像以提高安全性。对于业务系统,多个控制文件应该存放在不同的磁盘上,一般来说三个是足够的,如果只有两个物理硬盘,那么两个控制文件也是可以接受的。在同一个磁盘上保存多个控制文件是不具备实际意义的。
减少这个等待,可以考虑如下方法:
减少控制文件的个数(在确保安全的前提下)
如果系统支持,使用异步 IO
转移控制文件到 IO 负担轻的物理磁盘
13、control file sequential read/ control file single write 控制文件连续读/控制文件单个
写
对单个控制文件 I/O 存在问题时,这两个事件会出现。
如果等待比较明显,检查单个控制文件,看存放位置是否存在 I/O 瓶颈。
使用查询获得控制文件访问状态:
select P1 from V$SESSION_WAIT
where EVENT like 'control file%' and STATE='WAITING';
解决办法:
移动有问题的控制文件到快速磁盘
如果系统支持,启用异步 I/O
14、direct path write-直接路径写
该等待发生在,系统等待确认所有未完成的异步 I/O 都已写入磁盘。
对于这一写入等待,我们应该找到 I/O 操作最为频繁的数据文件(如果有过多的排序操作,很有可能就是临时文件),分散负载,加快其写入操作。
如果系统存在过多的磁盘排序,会导致临时表空间操作频繁,对于这种情况,可以考虑使用 Local 管理表空间,分成多个小文件,写入不同磁盘或者裸设备。
我们可以看一个 report 的典型例子:
DB Name DB Id Instance Inst Num Release Cluster Host
------------ ----------- ------------ -------- ----------- ------- ------------
DB 294605295 db 1 8.1.5.0.0 NO IBM
Snap Id Snap Time Sessions Curs/Sess Comment
------- ------------------- -------- --------- -------------------
Begin Snap: 65 08-11月-03 16:32:42 46 4.5
End Snap: 66 08-11月-03 16:54:00 46 5.0
Elapsed: 21.30 (mins)
这是一个 20 分钟的采样报告
Cache Sizes (end)
~~~~~~~~~~~~~~~~~
Buffer Cache: 51M Std Block Size: 16K
Shared Pool Size: 209M Log Buffer: 2097K
………………
Top 5 Timed Events
~~~~~~~~~~~~~~~~~~ % Total
Event Waits Time (s) Ela Time
-------------------------------------------- ------------ ----------- --------
direct path write 98,631 3,651 44.44
log file switch completion 62 2,983 36.31
direct path read 37,434 1,413 17.20
db file sequential read 86 109 1.33
control file sequential read 3,862 34 .41
-------------------------------------------------------------
我们注意到在 Top 5 等待事件中,最为显著的等待事件就是 direct path write。
基于此,我们继续向下追查相关排序部分统计数据:
Instance Activity Stats for DB: DB Instance: db Snaps: 65 -66
Statistic Total per Second per Trans
--------------------------------- ------------------ -------------- ------------
…………
sorts (disk) 64 0.1 0.4
sorts (memory) 861 0.7 4.7
sorts (rows) 2,804,580 15,159.9
…………
64次的 sort disk,相当显著的磁盘排序,对于这种情况,我们可以很容易的猜测到,临时表空间的读写操作肯定相当频繁:
File IO Statistics for DB: GHCXSDB Instance: ghcxsdb Snaps: 65- 66
Tablespace Filename
------------------------ ----------------------------------------------------
Reads Avg Blks Rd Avg Rd (ms) Writes Tot Waits Avg Wait (ms)
-------------- ----------- ----------- ----------------- -------------
………
PERFSTAT D:\ORACLE\ORADATA\PERFSTAT.DBF
88 1.0 12.5 821 0
RBS D:\ORACLE\ORADATA\GHCXSDB\RBS01.DBF
7 1.0 0.0 1,399 0
SYSTEM D:\ORACLE\ORADATA\GHCXSDB\SYSTEM01.DBF
17 1.0 11.8 50 0
TEMP D:\ORACLE\ORADATA\GHCXSDB\TEMP01.DBF
223,152 1.5 0.2 371,303 0
对于这种情况,我们建议,可以适当增加 sort_area_size 的大小,以缩减磁盘排序对于硬盘的写入,从而提高系统及应用相应。有一个测试数字可以参考:磁盘排序的时间大约是内存排序的 14000 倍。
15、slave wait-从属进程等
Slave Wait 是 Slave I/O 进程等待请求,是一个空闲参数,一般不说明问题。
16、Idle Event-空闲事件
最后我们来看几个空闲等待事件。
一般来说,空闲等待是指系统因为无事可做的等待,或者等待用户的请求或响应等,通常我们可以忽略这些等待事件。
空闲事件可以通过 stats$idle_event 表查询得到。
我们看一下系统的主要空闲等待事件,对这些事件大家应该有个大致的印象,如果你的 Top 5 等待事件中,主要都是这些事件,那么一般来说你的系统是比价清闲的:
SQL> select * from stats$idle_event;
EVENT
------------------------
smon timer
pmon timer
rdbms ipc message
Null event
parallel query dequeue
pipe get
client message
SQL*Net message to client
SQL*Net message from client
SQL*Net more data from client
dispatcher timer
virtual circuit status
lock manager wait for remote message
PX Idle Wait
wakeup time manager
15 rows selected.
-The End-