library cache lock/pin发生在多个session对相同library cache对象进行争用发生,一般来说在对象进行DDL时候发生,如:存储过程编译过程中发生并堵塞编译/表修改 解决方案:
======堵塞者和被堵塞者在同一节点 set linesize 500 col spid format a10 col username format a15 col machine format a15 col program format a20 col sql_fulltext format a100 select b.spid,a.sid,a.username,a.machine,a.program,c.sql_fulltext from v$session a,v$process b,v$sql c where a.paddr=b.addr and a.sql_id=c.sql_id and a.paddr in (SELECT s.paddr FROM x$kglpn p, v$session s WHERE p.kglpnuse = s.saddr(+) AND p.kglpnmod <> 0 and kglpnhdl in (select p1raw from v$session_wait where event in ('library cache pin', 'library cache lock', 'library cache load lock') ) ); / ======堵塞者和被堵塞者在不同一节点 1.在问题节点,查看是什么对象被PIN 在library cache中 set linesize 300 col owner for a20 col object for a20 SELECT KGLNAOWN owner,KGLNAOBJ object FROM x$kglob WHERE kglhdadr in(select P1RAW from v$session_wait where event like 'library cache%'); 2、在另外节点执行(带入上一个语句执行出的KGLNAOBJ) set linesize 300 col sql_text for a100 select sid, serial#, sql_text from dba_kgllock w, v$session s, v$sqlarea a where w.kgllkuse = s.saddr and s.sql_address = a.address and s.sql_hash_value = a.hash_value And w.kgllkhdl =(select kglhdadr from x$kglob where kglnaobj = 'PRO_YJB');
Latch:Library Cache
原因:为了寻找空闲Chunk,通过shared pool锁存器,实现保护扫描空闲列和分配适当Chunk;为了执行SQL。通过library cache锁存器,保护检索并管理库高速缓冲区的所有工作。在获得library cache锁存器过程中,若发生争用,则等待latch:library cache事件。library cache 锁存器争用主要在如下情况下发生: 1、Hard Parsing 或Soft Parsing 过多时 2、Version count如果很高,也会引发这个问题,因为找到handle以后, 对child的搜索是用遍历的方式,如果version很高child很多,则每次搜索的时间很可能会变长。会造成对handle上的锁,持有的时间也变长。 3、SGA区域发生Page out时,增加session_cache_cursors是个可能的尝试,如果cursor被cache住,child的位置会被保存在pga中,那么查找child的速度会明显加快
library cache: mutex X
11G以后,latch:library cache被替换为library cache: mutex X。锁的粒度变小,每个bucket和每个handle都被一个单独的mutex保护,大幅度减小了争用 1、当发生硬解析时,无论要创建一个新的handle,还是要创建一个新的Child,都需要额外大量的时间来完成,相应地,对这个mutex的持有时间会明显变长,造成争用。由于硬解析会向shared pool申请大量的内存,因此这种情况会伴随一系列其他等待如 latch: shared pool, library cache load lock。 解决办法就是分析硬解析过多,或者version count过高的问题。 2、OS资源不足,特别是CPU资源紧张。 这种情况下,oracle进程无法获取足够的资源去完成相应的工作,无法及时释放此mutex,造成请求的堆积。 3、再有,就是某个持有者长时间不释放此mutex,造成请求的积压。这是不正常的, 需要对mutex持有者的当前状态进行分析。 Errorstack, process dump。 如果持有者被其他进程阻塞,则通过hanganalyze等工具继续查找最终持有者 4、个别Oracle bug也会造成此类问题
latch:cache buffers chains
原因:欲在高速缓冲区上搜索特定块的进程,需要获得cache buffers chains锁存器。在此过程中,若发生争用,则等待latch:cache buffers chains事件。
1、不够优化的SQL。 大量逻辑读的SQL语句就有可能产生非常严重的latch:cache buffers chains等待,因为每次要访问一个block,就需要获得该latch,由于有大量的逻辑读,那么就增加了latch:cache buffers chains争用的机率。 对于正在运行的SQL语句,产生非常严重的latch:cache buffers chains争用,可以利用下面SQL查看执行计划,并设法优化SQL语句。select * from table(dbms_xplan.display_cursor('sql_id',sql_child_number)); 如果SQL已经运行完毕,我们就看AWR报表里面的SQL Statistics->SQL ordered by Gets->Gets per Exec,试图优化这些SQL。
2、热点块争用
2.1 查找数据库是否存在latch的争用select sid,event,p1text,p1raw from v$session_wait where event='latch: cache buffers chains'; 2.2 下面查询查出Top 5 的争用的latch address。 select * from( select CHILD#,ADDR,GETS ,MISSES,SLEEPS from v$latch_children where name = 'cache buffers chains' and misses>0 and sleeps>0 order by 5 desc, 1, 2, 3) where rownum<6;
3、然后利用下面查询找出Hot block。
select /*+ RULE */ e.owner ||'.'|| e.segment_name segment_name, e.extent_id extent#, x.dbablk - e.block_id + 1 block#, x.tch, /* sometimes tch=0,we need to see tim */x.tim ,l.child# from v$latch_children l, x$bh x, dba_extents e where x.hladdr = '&ADDR' and e.file_id = x.file# and x.hladdr = l.addr and x.dbablk between e.block_id and e.block_id + e.blocks -1 order by x.tch desc ; e.owner ||'.'|| e.segment_name segment_name, e.extent_id extent#, x.dbablk - e.block_id + 1 block#, x.tch, /* sometimes tch=0,we need to see tim */x.tim ,l.child# from v$latch_children l, x$bh x, dba_extents e where x.hladdr = '&ADDR' and e.file_id = x.file# and x.hladdr = l.addr and x.dbablk between e.block_id and e.block_id + e.blocks -1 order by x.tch desc ;
4、Hash Bucket太少 需要更改_db_block_hash_buckets隐含参数。其实在Oracle9i之后,我们基本上不会遇到这个问题了,除非遇到Bug。所以这个是不推荐的,记住,在对Oracle的隐含参数做修改之前一定要咨询Oracle Support。
latch:buffer cache lru chain
原因:高速缓冲区上与搜索空闲缓冲区(free buffer)和脏缓冲区(dirty buffer)的进程,需要获得cache buffers lru chain锁存器。在此过程中,若发生争用,则等待latch:cache buffers lru chain事件。
1、适当增大 Buffer Cache,这样可以减少读数据到 Buffer Cache 的机会,减少扫Lru List 的竞争。
2、可以适当增加 LRU Latch 的数量,修改_db_block_lru_latches 参数可以实现,但是该参数通常来说是足够的,除非在 Oracle Support 的建议下或确知该参数将带来的影响,否则不推荐修改。
3、通过多缓冲池技术,可以减少不希望的数据老化和全表扫等操作对于 Default池的冲击,从而可以减少竞争。
4、优化 SQL,减少数据读取,从而减少对于 LRU List 的扫描
