我们可以通过视图v$session_wait来查看系统当前的等待事件,以及与等待事件相对应的资源的相关信息,从而可确定出产生瓶颈的类型及其对象。v$session_wait的p1、p2、p3告诉我们等待事件的具体含义,根据事件不同其内容也不相同,下面就一些常见的等待事件如何处理以及如何定位热点对象和阻塞会话作一些介绍。
[@more@]<1> db file scattered read DB 文件分散读取
这种情况通常显示与全表扫描相关的等待。当全表扫描被限制在内存时,它们很少会进入
连续的缓冲区内,而是分散于整个缓冲存储器中。如果这个数目很大,就表明该表找不到
索引,或者只能找到有限的索引。尽管在特定条件下执行全表扫描可能比索引扫描更有效,
但如果出现这种等待时,最好检查一下这些全表扫描是否必要。因为全表扫描被置于LRU
(Least Recently Used,最近最少适用)列表的冷端(cold end),所以应尽量存储较小
的表,以避免一次又一次地重复读取它们。
该类事件的p1text=file#,p1是file_id,p2是block_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#,p1是file_id,p2是block_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 释放缓冲区等待
这种等待表明系统正在等待内存中的缓冲,因为内存中已经没有可用的缓冲空间了。如果
所有SQL 都得到了调优,这种等待可能表示你需要增大DB_BUFFER_CACHE。释放缓冲区等待
也可能表示不加选择的SQL 导致数据溢出了带有索引块的缓冲存储器,没有为等待系统处
理的特定语句留有缓冲区。这种情况通常表示正在执行相当多数量的DML(插入/更新/删
除),并且数据库书写器(DBWR)写的速度不够快,缓冲存储器可能充满了相同缓冲器的多
个版本,从而导致效率非常低。为了解决这个问题,可能需要考虑增加检查点、利用更多
的DBWR 进程,或者增加物理磁盘的数量。
<4> buffer busy waits 缓冲区忙等待
这是为了等待一个以非共享方式使用的缓冲区,或者正在被读入缓冲存储器的缓冲区。缓
冲区忙等待不应大于百分之一。检查缓冲等待统计部分(或V$WAITSTAT):
A、如果等待处于字段头部,应增加自由列表(freelist)的组数,或者增加pctused到
pctfree之间的距离。
B、如果等待处于回退段(undo)头部块,可以通过增加回滚段(rollback segment)来解决
缓冲区的问题;
C、如果等待处于回退段(undo)非头部块上,就需要降低驱动一致读取的表中的数据密
度,或者增大DB_CACHE_SIZE;
D、如果等待处于数据块,可以将数据移到另一数据块以避开这个"热"数据块、增加表中的
自由列表或使用LMT表空间;
E、如果等待处于索引块,应该重建索引、分割索引或使用反向键索引。
为了防止与数据块相关的缓冲忙等待,也可以使用较小的块:在这种情况下,单个块中的
记录就较少,所以这个块就不是那么"繁忙"。在执行DML(插入/更新/删除)时,Oracle
DBWR就向块中写入信息,包括所有对块状态"感兴趣"的用户(感兴趣的事务表,ITL)。为
了减少这一区域的等待,可以增加initrans,这样会在块中创建空间,从而使你能够使用
多个ITL槽。你也可以增加该块所在表中的pctfree(当根据指定的initrans 建立的槽数量
不足时,这样可以使ITL 信息数量达到maxtrans 指定的数量)。
<5> latch free
latch是一种低级排队机制(它们被准确地称为相互排斥机制),用于保护系统全局区域(SGA)
中共享内存结构。latch 就像是一种快速地被获取和释放的内存锁。latch 用于防止共享
内存结构被多个用户同时访问。如果latch 不可用,就会记录latch 释放失败。大多数
latch 问题都与以下操作相关:不能使用邦定变量(库缓存latch)、重复生成问题(重
复分配latch)、缓冲存储器竞争问题(缓冲器存储LRU 链),以及缓冲存储器中的"热"块
(缓冲存储器链)。也有一些latch 等待与bug(程序错误)有关,如果怀疑是这种情况,
可以检查MetaLink 上的bug 报告。
该事件的热点对象可通过以下语句查找,其中00000400837D7800值是v$session_wait中的
P1RAW
x$bh中的字段Hladdr表示该block buffer在哪个cache buffer chain latch 上,可以通过
v$latch_children定位哪些segment是热点块。
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 = '00000400837D7800'
union
select hladdr, file#, dbablk, tch, obj, null
from x$bh
where obj in
(select obj from x$bh
where hladdr = '00000400837D7800'
minus
select object_id from dba_objects
minus
select data_object_id from dba_objects)
and hladdr = '00000400837D7800'
order by 4;
<6> enqueue
enqueue 是一种保护共享资源的锁定机制。该锁定机制保护共享资源,如记录中的数据,
以避免两个人在同一时间更新同一数据。enqueue 包括一个排队机制,即FIFO(先进先出)
排队机制。注意:Oracle 的latch 机制不是FIFO。Enqueue 等待通常指的是ST enqueue、
HW enqueue、TX4 enqueue 和TM enqueue。
A、ST enqueue 用于空间管理和字典管理的表空间的分配。利用LMT,或者试图对区域进行
预分配,或者至少使下一个区域大于有问题的字典管理的表空间。
B、HW enqueue 与段的高水位标记一起使用;手动分配区域可以避免这一等待。
C、TX4 enqueue是最常见的enqueue 等待,通常是以下三个问题之一产生的结果:
第一个问题是唯一索引中的重复索引,需要执行提交(commit)/回滚(rollback)操
作来释放enqueue。
第二个问题是对同一位图索引段的多次更新。因为单个位图段可能包含多个行地址
(rowid),所以当多个用户试图更新同一段时,你需要执行提交或回滚操作,以释放enqueue。
第三个问题,也是最可能发生的问题是多个用户同时更新同一个块。如果没有自由的
ITL槽,就会发生块级锁定。通过增大initrans 和/或maxtrans以允许使用多个ITL槽,
或者增大表上的pctfree 值,就可以很轻松地避免这种情况。
D、TM enqueue 在DML 期间产生,以避免对受影响的对象使用DDL。如果有外来关键字,一
定要对它们进行索引,以避免这种常见的锁定问题。
<7> log buffer space 日志缓冲空间
当日志缓冲(log buffer)写入重做日志(redo log)的速度比LGWR 的写入速度慢,或者是
当日志转换(log switch)太慢时,就会发生这种等待。为解决这个问题,可以增大日志文
件的大小,或者增加日志缓冲器的大小,或者使用写入速度更快的磁盘。甚至可以考虑使
用固态磁盘,因为它们的速度很高。
<8> log file switch 日志文件转换
有两种情况:
A、log file switch (archiving needed)
当日志切换的时候由于日志组循环使用了一圈但日志归档还没有完成,通常是io有严重
问题,可增大日志文件和增加日志组,调整log_archive_max_processes
B、log 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引起冲突;放置日志文件于高速磁盘上
<10> 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=
这样,就可找到"library cache pin"等待的根源,从而解决由此引起的性能问题。
<11> library cache lock
该事件通常是由于执行多个DDL操作导致的,即在library cache 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或者其它处理。
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/3898/viewspace-853913/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/3898/viewspace-853913/