- Buffer busy waits
原因:
当一个会话试图修改一个数据块,但这个数据块正在被另一个会话修改时。
当一个会话需要读取一个数据块,但这个数据块正在被另一个会话读取到内存中时。
备注:数据处理的最小单位是块
select name,parameter1,parameter2,parameter3 from v$event_name where name='buffer busy waits';
NAME PARAMETER1 PARAMETER2 PARAMETER3
-------------------- ---------- ---------- ----------
buffer busy waits file# block# class#
File#:等待访问数据块所在的文件id号。
Blocks:等待访问的数据块号。
class#:原因码
A、如果等待处于字段头部,应增加自由列表(freelist)的组数,或者增加pctused到pctfree之间的距离。
B、如果等待处于回退段(undo)头部块,可以通过增加回滚段(rollback segment)来解决缓冲区的问题;
C、如果等待处于回退段(undo)非头部块上,就需要降低驱动一致读取的表中的数据密度,或者增大DB_CACHE_SIZE;
D、如果等待处于数据块,可以将数据移到另一数据块以避开这个"热"数据块、增加表中的自由列表或使用LMT表空间;
E、如果等待处于索引块,应该重建索引、分割索引或使用反向键索引。
问题处理:
select segment_type, owner || '.' || segment_name
from dba_extents
where file_id = file_id
and block_id between block_id and block_id + blocks - 1;
2、DB file scattered read
最常见的两种情况是全表扫描(FTS:Full Table Scan)和索引快速扫描(IFFS:index fast full scan)
3、Direct path read
当发生direct path read等待事件时,意味着磁盘上有大量的临时数据产生,比如排序,并行执行等操作。或者意味着PGA中空闲空间不足。
4、Direct path write
这个等待事件和direct path read正好相反,是会话将一些数据从PGA中直接写入到磁盘文件上,而不经过SGA。
这种情况通常发生在:
a.使用临时表空间排序(内存不足);
b.数据的直接加载(使用append方式加载数据);
c.并行DML操作。
5、Free buffer waits
当一个会话将数据块从磁盘读到内存中时,它需要到内存中找到空闲的内存空间来存放这些数据块,当内存中没有空闲的空间时,就会产生这个等待;除此之外,还有一种情况就是会话在做一致性读时,需要构造数据块在某个时刻的前映像(image),此时需要申请内存来存放这些新构造的数据块,如果内存中无法找到这样的内存块,也会发生这个等待事件。
当数据库中出现比较严重过的free buffer waits等待事件时,可能的原因是:
(1)、data buffer太小,导致空闲空间不够;
(2)、内存中的脏数据太多,DBWR无法及时将这些脏数据写到磁盘中以释放空间。
这个等待事件包含2个参数:
File#:需要读取的数据块所在的数据文件的文件号。
Block#:需要读取的数据块块号。
6、Library cache lock
一般可以理解的是alter table或者alter package/procedure会以X模式持有library cache lock,造成阻塞。
但是常见的问题还有以下几种原因:
1)错误的用户名密码:
2)正在执行搜集统计信息,这是大家往往会忽略的,一般会看last_ddl_time,却忽略了last_analyzed,
检查脚本如下:
比如EMP是遇到library cache lock中的表名:
select owner,object_name,object_type,to_char(last_ddl_time,'yyyy-mm-dd hh24:mi:ss') from dba_objects where object_name='EMP'; select table_name,to_char(last_analyzed,'yyyy-mm-dd hh24:mi:ss') from dba_tables where table_name='EMP';
也需要检查所有dependency的对象,因为oracle对象是相互关联的,一个对象失效会导致一串失效。
select owner,object_name,object_type,to_char(last_ddl_time,'yyyy-mm-dd hh24:mi:ss') ddl_time from dba_objects where object_name in ( select p.name from sys.obj$ d, sys.dependency$ dep, sys.obj$ p where d.obj# = dep.d_obj# and p.obj# = dep.p_obj# start with d.name='EMP' connect by prior dep.p_obj#=dep.d_obj#) order by ddl_time desc; select table_name,to_char(last_analyzed,'yyyy-mm-dd hh24:mi:ss') from dba_tables where table_name in ( select p.name from sys.obj$ d, sys.dependency$ dep, sys.obj$ p where d.obj# = dep.d_obj# and p.obj# = dep.p_obj# start with d.name='EMP' connect by prior dep.p_obj#=dep.d_obj#) order by last_analyzed desc;
3)错误的语句解析(failed parse)
4)bug
7、Library cache pin
这个等待事件和library cache lock一样是发生在共享池中并发操作引起的事件。通常来讲,如果Oracle要对一些PL/SQL或者视图这样的对象做重新编译,需要将这些对象pin到共享池中。
如果此时这个对象被其他的用户特有,就会产生一个library cache pin的等待。
8、Log buffer space
当log buffer中没有可用空间来存放新产生的redo log数据时,就会发生log buffer space等待事件。如果数据库中新产生的redo log的数量大于LGWR写入到磁盘中的redo log数量,必须等待LGWR完成写入磁盘的操作,LGWR必须确保redo log写到磁盘成功之后,才能在redo buffer当中重用这部分信息。
如果数据库中出现大量的log buffer space等待事件,可以考虑如下办法:
(1)、增加redo buffer的大小。
(2)、提升磁盘的I/O性能。
9、Log file sequential read
这个等待事件通常发生在对redo log信息进行读取时,比如在线redo的归档操作,ARCH进程需要读取redo log的信息,由于redo log的信息是顺序写入的,所以在读取时也是按照顺序的方式来读取的。
10、Log file switch(archiving needed)
在归档模式下,这个等待事件发生在在线日志切换(log file switch)时,需要切换的在线日志还没有被归档进程(ARCH)归档完毕的时候。当在线日志文件切换到下一个日志时,需要确保下一个日志文件已经被归档进程归档完毕,否则不允许覆盖那个在线日志信息(否则会导致归档日志信息不完整)。
出现这样的等待事件通常是由于某种原因导致ARCH进程死掉,比如ARCH进程尝试向目的地写入一个归档文件,但是没有成功(介质失效或者其他原因),这时ARCH进程就会死掉。如果发生这种情况,在数据库的alert log文件中可以找到相关的错误信息。
11、Log file switch(checkpoint incomplete)
当一个在线日志切换到下一个在线日志时,必须保证要切换到的在线日志上的记录信息(比如一些脏数据块产生的redo log)被写到磁盘上(checkpoint),这样做的原因是,如果一个在线日志文件的信息被覆盖,而依赖这些redo信息做恢复的数据块尚未被写到磁盘上(checkpoint) ,此时系统down掉的话,Oracle将没有办法进行实例恢复。
在v$log视图里记录了在线日志的状态。通常来说,在线日志有三种状态。
Active:这个日志上面保护的信息还没有完成checkpoint。
Inactive:这个日志上面保护的信息已完成checkpoint。
Current:当前的日志。
Oracle在做实例恢复时,会使用状态为current和active的日志进行实例恢复。
如果系统中出现大量的log file switch(checkpoint incomplete)等待事件,原因可能是日志文件太小或者日志组太少,所以解决的方法是,增加日志文件的大小或者增加日志组的数量。
12、Log file sync
引起log file sync的原因:
1.频繁提交或者rollback,检查应用是否有过多的短小的事务,如果有,可以使用批处理来缓解。
2.OS的IO缓慢:解决办法是将日志文件放裸设备上或绑定在RAID 0或RAID 1+0中,而不是绑定在RAID 5中。
3.过大的日志缓冲区(log_buffer ) 过大的log_buffer,允许LGWR变得懒惰,因为log buffer中的数据量无法达不到_LOG_IO_SIZE,导致更多的重做条目堆积在日志缓冲区中。
当事务提交或者3s醒来时,LGWR才会把所有数据都写入到redo log file中。 由于数据很多,LGWR要用更多时间等待redo写完毕。
这种情况,可以调小参数_LOG_IO_SIZE参数,其默认值是LOG_BUFFER的1/3或1MB,取两者之中较小的值。
换句话说,你可以具有较大的日志缓冲区,但较小的_LOG_IO_SIZE将增加后台写入次数,从而减少log file sync的等待时间。
4.CPU负载高。详见下面的描述。
5.RAC私有网络性能差,导致LMS同步commit SCN慢
判断:
1.如果log file sync的等待时间很高,而log file parallel write的等待时间并不高,这意味着log file sync的原因并不是缓慢的日志I/O,而是应用程序过多的提交造成。
当log file sync的等待时间和 log file parallel write等待时间基本相同,说明是IO问题造成的log file sync等待事件。
2.Lgwr trace file(10.2.0.4开始),大于500ms会写入
trace文件中如果有Warning: log write time 1000ms, size 2KB,很有可能IO慢。3.分析CPU资源使用情况的工具,CPU过于繁忙,lgwr无法及时获取CPU调度,出现log file sync。
vmstat,关注r是否大于CPU核数,大于说明cpu繁忙。
log file sync=CPU+几个latch+log file parallel write(此处latch申请一般不是瓶颈)
--如果log file sync远大于log file parallel write的等待时间,只会为以下三种情况
1、CPU资源紧张
2、LGWR在申请latch资源时遇到竞争(IMU未使用,RAC环境下不适用)
3、同时提交的进程太多
解决办法:
1.如果确实是因为频繁提交造成的log file sync,那么减少commit,批量提交。
2.如果确实是因为io引起的,那么解决办法是将日志文件放裸设备上或绑定在RAID 1+0中,而不是放在在RAID 5中(切记,redo log file一定不要放在SSD上!!!)。
3.确保CPU资源充足。CPU资源不足,LGWR通知user session后,user session无法及时获得CPU调度,不能正常工作。
4.是否有些表可以使用nologging,会减少redo产生量5.检查redo log file足够大,确保redo log file每15到20分钟切换一次。
13、cursor: pin S wait on X
cursor: pin S,cursor: pin X,cursor: pin S wait on X这三个等待事件,实际上就是替代了cursor的library cache pin,pin S代表执行(share pin),pin X代表解析(exclusive pin),
pin S wait on X代表执行正在等待解析操作。
这里需要强调一下,它们只是替换了访问cursor的library cache pin,而对于访问procedure这种实体对象,依然是传统的library cache pin。
cursor: pin S wait on X,这个等待事件主要是由硬解析引起的
--硬解析,软解析,软软解析在共享池中的等待事件
1、硬解析:latch: shared pool,硬解析需要所有类型的mutex,包括library cache: mutex,cursor: pin,HASH Table,cursor Parent
2、软解析:library cache: mutex,cursor: pin,HASH Table,cursor Parent
3、软软解析(将子游标堆6的信息,缓存在PGA中。子游标堆6:保存执行计划信息):两次cursor: pin S和一次library cache: mutex X(如果使用绑定变量或且使用静态游标,会导致一次library cache: mutex X)
4、sql版本过多:library cache和HASH Table类型等待
总结:如果只有cursor: pin类型和library cache: mutex型竞争激烈,是软软解析问题;如果还有其他类mutex型等待,则是软解析导致。如果再有shared pool latch竞争激烈,一定是硬解析过多,由于大量进程同时请求从共享池中分配内存导致;
版本过多的硬解析:library cache lock和HASH Table类型等待同时出现,如果只有HASH Table类型等待而没有library cache lock,则是版本过多的父游标有很多并发的软解析。
硬解析导致异常等待处理:使用绑定变量(应用层面),cursor sharing=true 禁用ACS(adaptive cursor sharing),配置充足的shared pool v$sqlarea sql_text列中相似的sql很多,说明未使用绑定变量
软解析争用处理:调整session cached cursors参数,使软解析变为软软解析
软软解析导致争用处理:cursor pin:s ,使用提示符/**/改变sql hash值,将一条SQL变为多条减少争用;应用层缓存游标,实现一次解析,多次执行
--导致oracle high version count(高版本游标)
原因:1、owner不同 2、表统计信息发生变化 3、系统环境统计信息发生变化
SELECT * FROM v$sql_shared_cursor e WHERE e.SQL_ID = 'a4tjn5xjzx2mt'
绑定变量长度变大会导致BIND_MISMATCH
14、latch:cache buffers chains
一般产生CACHE BUFFERS CHAINS的原因有几个方面:
1、buffer cache太少(也说明SQL语句效率低,较多的逻辑读意味着较多的latch get操作,从而增加了锁存器争用。多个进程同时扫描大范围的索引或表时,可能广泛地发生cache buffers chains 锁存器争用);
2、热块挣用。(从oracle9i开始,对latch:cache buffer chains支持只读共享访问,这可以减少部分争用,但并不能完全消除争用。)
当多个会话重复访问一个或多个由同一个子cache buffers chains锁存器保护的块时,就会产生热块挣用。当多个会话争用cache buffers chains锁存器时,找出是否有热块的最好的方法是检查latch free等待事件的P1RAW参数值。
判断热块挣用的另一种方法是从 v$session_wait 视图获得锁存器地址后进行比较。v$session_wait的P1RAW就相当于子锁存器地址,若从 v$session_wait 视图获得的锁存器地址过多重复出现,就意味着对相应锁存器发生次数偏多,此时可解释为热快引起的争用。如果会话正在相同的锁存器地址上等待,就是热块。
SQL> select sid,p1raw,p2,p3,seconds_in_wait,wait_time,state from v$session_wait where event='latch: cache buffers chains' order by 3,2;
使用P1RAW=00000300DA316800为例子进行关联热快对象。
SQL> select a.hladdr,a.file#,a.dbablk,a.tch,a.obj,b.object_name from x$bh a, dba_objects b where (a.obj = b.object_id or a.obj = b.data_object_id) and a.hladdr = '00000300DA316800' union select hladdr,file#,dbablk,tch,obj,null from x$bh where obj in (select obj from x$bh where hladdr = '00000300DA316800' minus select object_id from dba_objects minus select data_object_id from dba_objects) and hladdr = '00000300DA316800' order by 4;