今天重新阅读Latch的文档,按照我自己的理解,对于vlatch视图中的以下几个字段再作一些解释。
以下参数都是对于Willing-to-wait模式的latch而言的,no-wait模式的latch获得情况统计值则在IMMEDIATE_GETS和IMMEDIATE_MISSES字段中。所有vlatch视图中统计值都是在获得了latch之后才更新的。
GETS:当尝试获取一个latch并最终获得的时候,该值加1,在一次请求中无论是经过多少次自旋多少次Sleep,该值只会加1.
MISSES:如果没能不经过自旋(spin)就获得latch,该值加1,在一次请求中无论是经过多少次自旋多少次Sleep,该值只会加1.
SPIN_GETS:如果经过自旋才获得latch,该值加1,在一次请求中无论是经过多少次自旋,该值只会加1;如果经过了下述的SLEEPS方式才获得的latch,那么该值不变。
SLEEPS:这是MISS之后进程除了自旋之外,可能采取的另外一种方式-睡眠,将等待信号量唤醒或者Timeout唤醒。可能是由于多次自旋以后,仍然无法获得latch,进程就停止占用CPU,进入Sleep状态;也可能是首次尝试获取latch失败以后就直接进入睡眠期(比如单个CPU的机器中)。Sleep以后获得latch,该值加1,如果一次Sleep以后被唤醒,但是却仍然无法获得latch,那么会再次自旋,还无法获得,再次Sleep(睡眠时间会逐渐变长),多次Sleep会累加该值。
SQL> select count(*) from v$latch where MISSES=0;
COUNT(*)
----------
484
如上所示,这些latch都是一次请求就直接成功了,连一次Miss都没有。只要MISSES=0,那么SPIN_GETS和SLEEPS也一定等于0。
SQL> select NAME,GETS,MISSES,SPIN_GETS,SLEEPS from v$latch where MISSES>0 and SLEEPS=0;
NAME GETS MISSES SPIN_GETS SLEEPS
---------------------------------------- ---------- ---------- ---------- ----------
process allocation 31557 8 8 0
session switching 32313 3 3 0
process group creation 24916 1 1 0
object stats modification 171932 93 93 0
parameter table management 38297 28 28 0
enqueue freelist latch 407 28 28 0
FOB s.o list latch 68402 13 13 0
FIB s.o chain latch 416 1 1 0
resmgr:free threads list 29002 55 55 0
resmgr group change latch 1691466 79 79 0
channel handle pool latch 28121 4 4 0
message pool operations parent latch 97758 128 128 0
ksv class latch 25738 66 66 0
OS process allocation 2402435 7 7 0
ksz_so allocation latch 24916 8 8 0
mostly latch-free SCN 931660 715 715 0
lgwr LWN SCN 930897 73 73 0
Consistent RBA 807421 43 43 0
multiblock read objects 256976 10 10 0
cache table scan latch 95413 5 5 0
managed standby latch 32933 15 15 0
list of block allocation 64850 24 24 0
transaction allocation 199415 55 55 0
KTF sga latch 7195 2 2 0
resmgr:resource group CPU method 8868 21 21 0
parameter list 59369 8 8 0
job_queue_processes free list latch 699 1 1 0
process queue reference 5500 1 1 0
parallel query alloc buffer 163672 1 1 0
hash table modification latch 52632 6 6 0
temporary table state object allocation 2939 14 14 0
SQL memory manager latch 41293 1 1 0
SQL memory manager workarea list latch 28598806 49 49 0
session state list latch 34530 1 1 0
34 rows selected.
如上所示,这些latch都有请求没有立刻成功的情况,因此都需要Spin片刻然后再次尝试获取,但是却都在Spin一次或者几次以后(在第一次Sleep之前最多自旋2000次,受隐含参数_spin_count控制)就成功获得了latch,注意所有行的MISSES=SPIN_GETS,也就是说如果某个latch在被尝试获取的时候从来都没有让进程Sleep过,那么只要出现1次Miss,就必须有至少1次Spin,而直到成功获得latch之前,无论有多少次Spin,SPIN_GETS值都始终只是加了1。
SQL> select NAME,GETS,MISSES,SPIN_GETS,SLEEPS from v$latch where MISSES>0 and MISSES<>SPIN_GETS;
NAME GETS MISSES SPIN_GETS SLEEPS
---------------------------------------- ---------- ---------- ---------- ----------
post/wait queue 2176086 6243 6215 28
call allocation 140862 79 50 29
session allocation 1366266 208 194 14
session idle bit 21495388 2581 2552 29
ksuosstats global area 124206 13 0 13
messages 16534632 7141 7076 66
enqueue hash chains 14685159 6740 6613 127
channel operations parent latch 6197125 261 233 28
active service list 1343611 36 17 19
OS process: request allocation 24916 16 7 9
cache buffers lru chain 3932233 3750 3587 166
active checkpoint queue latch 1657410 315 283 32
checkpoint queue latch 36991888 796 759 37
cache buffers chains 385956869 13902 13573 335
cache buffer handles 115915 1 0 1
simulator lru latch 1730616 70 61 9
simulator hash latch 11343463 16 11 5
object queue header operation 24499957 7389 7149 241
object queue header heap 6170931 465 459 6
archive process latch 99017 77 12 65
redo writing 4799991 1133 1131 2
redo allocation 2703585 1256 1022 234
DML lock allocation 2340322 302 291 11
dummy allocation 25610 44 26 18
undo global data 5721900 1143 1126 17
sort extent pool 55723 88 87 1
space background task latch 1653230 12640 12624 17
sequence cache 37261 6 0 7
row cache objects 57918735 298666 298342 334
shared pool 14914798 80691 71271 12265
resmgr:actses change state 12453 1 0 1
resmgr:schema config 1792347 2144 2124 20
shared pool simulator 645495 44 43 1
hash table column usage latch 73186 300 299 1
qmn task queue latch 179150 8 0 8
35 rows selected.
如上所示,只要曾经MISS过,但MISSES<>SPIN_GETS,那么必然意味着会有SLEEPS出现。SLEEPS之后,就不再累加本次的SPIN_GETS,因此所有的SPIN_GETS值才会都小于MISSES。
注意到其中有多个latch,完全没有经过Spin,而是每次都直接Sleep了,我的理解是对于某些latch,Oracle就直接选择了Sleep方式而不会尝试自旋(即使是在多CPU机器中)。以下这些latch都是这种模式,不会进行Spin,而是直接进入Sleep状态,等待唤醒然后再尝试获取latch。
SQL> select NAME,GETS,MISSES,SPIN_GETS,SLEEPS from v$latch where SPIN_GETS=0 and SLEEPS>0;
NAME GETS MISSES SPIN_GETS SLEEPS
---------------------------------------- ---------- ---------- ---------- ----------
ksuosstats global area 124216 13 0 13
cache buffer handles 115915 1 0 1
sequence cache 37261 6 0 7
resmgr:actses change state 12454 1 0 1
qmn task queue latch 179166 8 0 8
希望以上描述可以更清晰地了解Latch是如何获得的,总结一下,在v$latch中,
1. MISSES=0: 表示请求以后就立刻获得了latch。
2. MISSES>0 and SLEEPS=0:表示请求以后没有获得latch,但是通过自旋获得了latch。
3. MISSES>0 and SLEEPS>0:表示请求以后没有获得latch,并且通过2000次自旋也没有获得latch,从而进入了Sleep;或者根本没有自旋就直接进入了Sleep。
如上所示,只要曾经MISS过,但MISSES<>SPIN_GETS,那么必然意味着会有SLEEPS出现。SLEEPS之后,就不再累加本次的SPIN_GETS,因此所有的SPIN_GETS值才会都小于MISSES。
请问这个怎么理解?除去misses后直接sleeps的情况,misses为什么会不等于spin_gets呢
@ian
MISSES=SPIN_GETS+SLEEPS(基本上如此)
进入sleep以后,仍然会累加MISSES,但是已经不再累加SPIN_GETS。