Oracle等待事件以及解决方案


Oracle等待事件以及解决方案

我们可以通过视图v$session_wait查看系统当前的等待事件,以及与等待事件相对应的资源的相关信息,从而可确定出产生瓶颈的类型及其对象。 v$session_waitp1p2p3告诉我们等待事件的具体含义,根据事件不同其内容也不相同,下面就一些常见的等待事件如何处理以及如何定位热点对象和阻塞会话作一些介绍。


<1> db file scattered read DB 文件分散读取 (太多索引读,全表扫描-----调整代码,将小表放入内存)
这种情况通常显示与全表扫描相关的等待。当全表扫描被限制在内存时,它们很少会进入连续的缓冲区内,而是分散于整个缓冲存储器中。如果这个数目很大,就表明该表找不到索引,或者只能找到有限的索引。尽管在特定条件下执行全表扫描可能比索引扫描更有效,但如果出现这种等待时,最好检查一下这些全表扫描是否必要。因为全表扫描被置于LRU(Least Recently Used,最近最少使)列表的冷端(cold end),所以应尽量存储较小的表,以避免一次又一次地重复读取它们。
==================================================
该类事件的p1text=file#,p1file_idp2block_id,通过dba_extents即可确定出热点对象(表或索引)
select owner,segment_name,segment_type
from dba_extents
where file_id = &file_id
and &block_id between block_id and block_id + &blocks - 1;
==================================================


<2> db file sequential read DB 文件顺序读取 (表连接顺序不佳-----调整代码,特别是表连接)
这一事件通常显示单个块的读取(如索引读取)。这种等待的数目很多时,可能显示表的连接顺序不佳,或者不加选择地进行索引。对于大量事务处理、调整良好的系统,这一数值大多是很正常的,但在某些情况下,它可能暗示着系统中存在问题。你应当将这一等待统计量与Statspack 报告中的已知问题(如效率较低的SQL)联系起来。检查索引扫描,以保证每个扫描都是必要的,并检查多表连接的连接顺序。DB_CACHE_SIZE 也是这些等待出现频率的决定因素。有问题的散列区域(Hash-area)连接应当出现在PGA 内存中,但它们也会消耗大量内存,从而在顺序读取时导致大量等待。它们也可能以直接路径读/写等待的形式出现。
===================================================
该类事件的p1text=file#,p1file_idp2block_id,通过dba_extents即可确定出热点对象(表或索引)
select owner,segment_name,segment_type
from dba_extents
where file_id = &file_id
and &block_id between block_id and block_id + &blocks - 1;
==================================================


<3> free buffer waits 释放缓冲区等待 (增大DB_CACHE_SIZE,加速检查点,调整代码)
这种等待表明系统正在等待内存中的缓冲,因为内存中已经没有可用的缓冲空间了。如果所有SQL 都得到了调优,这种等待可能表示你需要增大DB_BUFFER_CACHE。释放缓冲区等待也可能表示不加选择的SQL 导致数据溢出了带有索引块的缓冲存储器,没有为等待系统处理的特定语句留有缓冲区。这种情况通常表示正在执行相当多数量的DML(插入/更新/删除),并且数据库书写器(DBWR)写的速度不够快,缓冲存储器可能充满了相同缓冲器的多个版本,从而导致效率非常低。为了解决这个问题,可能需要考虑增加检查点、利用更多的DBWR 进程,或者增加物理磁盘的数量。


<4> buffer busy waits 缓冲区忙等待 (BUFFER热块)
这是为了等待一个以非共享方式使用的缓冲区,或者正在被读入缓冲存储器的缓冲区。缓冲区忙等待不应大于1%。检查缓冲等待统计部分(或V$WAITSTAT:
A、如果等待处于字段头部,应增加自由列表(freelist)的组数,或者增加pctusedpctfree之间的距离。
B、如果等待处于回退段(undo)头部块,可以通过增加回滚段(rollback segment)来解决缓冲区的问题;
C、如果等待处于回退段(undo)非头部块上,就需要降低驱动一致读取的表中的数据密度,或者增大DB_CACHE_SIZE
D、如果等待处于数据块,可以将数据移到另一数据块以避开这个""数据块、增加表中的自由列表或使用LMT表空间;
E、如果等待处于索引块,应该重建索引、分割索引或使用反向键索引。
为了防止与数据块相关的缓冲忙等待,也可以使用较小的块:在这种情况下,单个块中的记录就较少,所以这个块就不是那么"繁忙"。在执行DML(插入/更新 /删除),Oracle DBWR就向块中写入信息,包括所有对块状态"感兴趣"的用户(感兴趣的事务表,ITL)。为减少这一区域的等待,可以增加initrans,这样会在块中创建空间,从而使你能够使用多个ITL槽。你也可以增加该块所在表中的pctfree(当根据指定的initrans 建立的槽数量不足时,这样可以使ITL 信息数量达到maxtrans 指定的数量)。


<6> enqueue
enqueue 是一种保护共享资源的锁定机制。该锁定机制保护共享资源,如记录中的数据,以避免两个人在同一时间更新同一数据。enqueue 包括一个排队机制,即FIFO(先进先出)排队机制。注意:Oracle latch 机制不是FIFOEnqueue 等待通常指的是ST enqueueHW enqueueTX4 enqueue TM enqueue
AST enqueue 用于空间管理和字典管理的表空间的分配。利用LMT,或者试图对区域进行预分配,或者至少使下一个区域大于有问题的字典管理的表空间。
BHW enqueue 与段的高水位标记一起使用;手动分配区域可以避免这一等待。
CTX4 enqueue是最常见的enqueue 等待,通常是以下三个问题之一产生的结果:
第一个问题是唯一索引中的重复索引,需要执行提交(commit/回滚(rollback)操作来释放enqueue。第二个问题是对同一位图索引段的多次更新。因为单个位图段可能包含��个行地址(rowid),所以当多个用户试图更新同一段时,你需要执行提交或回滚操作,以释放enqueue
第三个问题,也是最可能发生的问题是多个用户同时更新同一个块。如果没有自由的ITL槽,就会发生块级锁定。通过增大initrans /maxtrans以允许使用多个ITL槽,或者增大表上的pctfree 值,就可以很轻松地避免这种情况。
DTM enqueue DML 期间产生,以避免对受影响的对象使用DDL。如果有外来关键字,一定要对它们进行索引,以避免这种常见的锁定问题。


<7> log buffer space 日志缓冲空间 (REDO-----增大log_buffer,redo log file放到快速磁盘上)
当日志缓冲(log buffer)写入重做日志(redo log)的速度比LGWR 的写入速度慢,或者是当日志转换(log switch)太慢时,就会发生这种等待。为解决这个问题,可以增大日志文件的大小,或者增加日志缓冲器的大小,或者使用写入速度更快的磁盘。甚至可以考虑使用固态磁盘,因为它们的速度很高。


<8> log file switch 日志文件转换 (归档慢-----增加或者扩大重做日志)
有两种情况:
Alog file switch (archiving needed)
当日志切换的时候由于日志组循环使用了一圈但日志归档还没有完成,通常是io有严重问题,可增大日志文件和增加日志组,调整log_archive_max_processes
Blog file switch (checkpoint incomplete)
当日志切换的时候由于日志组循环使用了一圈但将被使用的日志组中的checkpoint还没有完成造成,通常是io有严重问题,可增大日志文件和增加日志组


<9> log file sync 日志文件同步 (交太频繁----批量提交)
当用户commit的时候通知lgwr写日志但lwgr正忙,造成的可能原因是commit太频繁或者lgwr一次写日志时间太长(可能是因为一次log io size 太大),可调整 _log_io_size,结合log_buffer,使得 (_log_io_size*db_block_size)*n = log_buffer,这样可避免和增大log_buffer引起冲突;放置日志文件于高速磁盘上

  • 1
  • 2
  • 下一页

相关内容