Event Waits Time (s) Ela Time
-------------------------------------------- ------------ ----------- --------
CPU time 361 54.14
log file sync 74,324 101 15.22
enqueue 729 88 13.28
db file sequential read 7,303 65 9.76
SQL*Net message from dblink 482 20 3.05
/* 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 秒的)运行的事物,可能很多是全表扫描操作(不管怎样,这部分信息都是值得我们注意的)。
2) db file sequential read:该事件说明在单个数据块上大量等待,该值过高通常是由于表间连接顺序很糟糕(没有正确选择驱动行源),或者使用了非选择性索引。通过将这种等待与statspack报表中已知其它问题联系起来(如效率不高的sql),通过检查确保索引扫描是必须的,并确保多表连接的连接顺序来调整。
3) buffer busy wait:当缓冲区以一种非共享方式或者如正在被读入到缓冲时,就会出现该等待。该值不应该大于1%。当出现等待问题时,可以检查缓冲等待统计部分(或V$WAITSTAT),确定该等待发生在什么位置:
a) 如果等待是否位于段头(Segment Header)。这种情况表明段中的空闲列表(freelist)的块比较少。可以考虑增加空闲列表(freelist,对于Oracle8i DMT)或者增加freelist groups(在很多时候这个调整是立竿见影的(alter table sp_item strorage(freelists 2)),在8.1.6之前,这个freelists参数不能动态修改;在8.1.6及以后版本,动态修改feelists需要设置COMPATIBLE至少为8.1.6)。也可以增加PCTUSED与PCTFREE之间距离(PCTUSED-to-pctfree gap),其实就是说降低PCTUSED的值,尽快使返回freelist列表被重用。如果支持自动段空间管理(ASSM),也可以使用ASSM模式。
b) 如果这一等待位于undo header,可以通过增加回滚段(rollback segment)来解决缓冲区的问题。
c) 如果等待位于undo block上,我们需要增加提交的频率;使用更大的回滚段,降低一致读所选择的表中数据的密度;增大DB_CACHE_SIZE。
d) 如果等待处于data block,表明出现了hot block,可以考虑如下方法解决: ①将频繁并发访问的表或数据移到另一数据块或者进行更大范围的分布(可以增大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(Segment Space Management Auto)。通过这个新特性Oracle 使用位图来管理空间使用。
4) latch free:当闩锁丢失率高于0.5%时,需要调整这个问题。详细的我们在后面的Latch Activity for DB部分说明。
5) Enqueue 队列是一种锁,保护一些共享资源,防止并发的DML操作。队列采用FIFO策略,注意latch并不是采用的FIFO机制。比较常见的有3种类型的队列:ST队列,HW队列,TX4队列。
ST Enqueue的等待主要是在字典管理的表空间中进行空间管理和分配时产生的。解决方法:1)将字典管理的表空间改为本地管理模式 2)预先分配分区或者将有问题的字典管理的表空间的next extent设置大一些。
HW Enqueue是用于segment的HWM的。当出现这种等待的时候,可以通过手工分配etents来解决。
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,这样每个块中包含行就比较少,可以减小冲突发生的机会。
6) Free Buffer:这个等待事件表明系统正在等待内存中的可用空间,这说明当前Buffer 中已经没有Free 的内存空间。如果应用设计良好,SQL 书写规范,充分绑定变量,那这种等待可能说明Buffer Cache 设置的偏小,你可能需要增大DB_BUFFER_CACHE。该等待也可能说明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 buffer space:日志缓冲区写的速度快于LGWR写REDOFILE的速度,可以增大日志文件大小,增加日志缓冲区的大小,或者使用更快的磁盘来写数据。
10) 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 或者增加你的日志组或日志文件大小。
11) log file sync:当一个用户提交或回滚数据时,LGWR将会话得重做操作从日志缓冲区填充到日志文件中,用户的进程必须等待这个填充工作完成。在每次提交时都出现,如果这个等待事件影响到数据库性能,那么就需要修改应用程序的提交频率, 为减少这个等待事件,须一次提交更多记录,或者将重做日志REDO LOG 文件访在不同的物理磁盘上。
12) DB File Parallel Write:改善IO性能
13) Direct Path Read:一般直接路径读取是指将数据块直接读入PGA中。一般用于排序、并行查询和read ahead操作。这个等待可能是由于I/O造成的。使用异步I/O模式或者限制排序在磁盘上,可能会降低这里的等待时间。
14) direct path write:直接路径写该等待发生在,系统等待确认所有未完成的异步I/O 都已写入磁盘。对于这一写入等待,我们应该找到I/O 操作最为频繁的数据文件(如果有过多的排序操作,很有可能就是临时文件),分散负载,加快其写入操作。如果系统存在过多的磁盘排序,会导致临时表空间操作频繁,对于这种情况,可以考虑使用Local管理表空间,分成多个小文件,写入不同磁盘或者裸设备。
15) control file parallel write:当server 进程更新所有控制文件时,这个事件可能出现。如果等待很短,可以不用考虑。如果等待时间较长,检查存放控制文件的物理磁盘I/O 是否存在瓶颈。
多个控制文件是完全相同的拷贝,用于镜像以提高安全性。对于业务系统,多个控制文件应该存放在不同的磁盘上,一般来说三个是足够的,如果只有两个物理硬盘,那么两个控制文件也是可以接受的。在同一个磁盘上保存多个控制文件是不具备实际意义的。减少这个等待,可以考虑如下方法:①减少控制文件的个数(在确保安全的前提下)。②如果系统支持,使用异步IO。③转移控制文件到IO 负担轻的物理磁盘。
16) control file sequential read
control file single write :控制文件连续读/控制文件单个写对单个控制文件I/O 存在问题时,这两个事件会出现。如果等待比较明显,检查单个控制文件,看存放位置是否存在I/O 瓶颈。
常见的一些IDLE wait事件举例:
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
SQL*Net message from client