latch是ORACLE中锁的一种,它是一种低级锁,是保护SGA中的共享内存,它几乎不排队(latches wait list除外),不会产生死锁。
latch分为no-wait与willing-to-wait模式,以willing-to-wait请求的latch只有少数几个,而且他们一般都有多个子latch.
比如redo copy latch,我们知道redo 最开始产生于PGA中,之后会将redo记录copy到SGA中,要想copy,就需要获得一个
redo copy latch,防止copy过程中redo记录被破坏。而redo copy latch的获取方式是 no-wait方式的,如果请求没有获得,它不会在cpu上面自旋(spin,当然你需要有多个CPU),而是继续以no-wait方式继续请求,因为有多个redo copy latch,很容易获得一个redo copy latch,如果所有的redo copy latch都无法获得,那么就只好以willing-to-wait模式请求redo copy latch了。
以no-wait模式请求latch,会在v$latch.immediate_gets,immediate_misses中记录。
绝大多数的latch都是以will-to-wait模式请求的。他们的信息会记录在gets,misses列。
在多cpu系统中以willing-to-wait模式请求latch过程如下:
1.请求latch,如果没有别的进程拥有该latch,那么直接获得该latch.
2.如果latch被别的进程持有,请求该latch的进程在cpu上自旋一段时间,自旋的次数和时间长短由cpu决定。如果是单cpu,不会自旋,直接休眠。
3.从新尝试获得该latch,如果无法获取(_spin_count次自旋后),记录一个latch free等待事件,然后释放cpu,休眠。如果获得了该latch,则在spin_gets,misses列上加一,自旋的总的次数由_spin_count隐含参数决定。
4.睡眠结束后,继续尝试获取该latch,直到获得该latch为止,同时获得latch的时候会更新sleeps列的信息。
可以查看v$system_event.total_waits来查看latch无法获取的次数,v$system_event.total_waits应该等于v$latch.sleeps,不过因为sleeps是在latch获得之后才更新的,所以tatal_waits查询出来的时候通常大于sleeps。
SQL> select event,total_waits,time_waited,average_wait from v$system_event where event like '%latch%' ;
EVENT TOTAL_WAITS TIME_WAITED AVERAGE_WAIT
---------------------------------------------------------------- ----------- ----------- ------------
latch: cache buffers chains 2 0 0
latch: shared pool 3 0 .06
latch: library cache 1 0 .01
latch free 6 0 0
latch: session allocation 1 0 .01
latch: cache buffers lru chain 3 9 2.86
已选择6行。
SQL> select name,gets,misses,sleeps,spin_gets from v$latch where sleeps!=0;
NAME GETS MISSES SLEEPS SPIN_GETS
-------------------------------------------------- ---------- ---------- ---------- ----------
shared pool 109039 204 3 201
session allocation 264876 307 1 306
cache buffers lru chain 19276 19 3 16
qmn task queue latch 78 9 6 3
library cache 83505 83 1 82
cache buffers chains 960520 47 2 46
已选择6行。
可以看到cache buffers chains 中v$system_event.total_waits等于v$latch.sleeps。
misses通常比spin_gets大,但是他们很接近,gets通常较大,因为每次请求一个latch就会加一。