About GETS, MISSES, SPIN_GETS, SLEEPS in V$LATCH

on

今天重新阅读Latch的文档,按照我自己的理解,对于v$latch视图中的以下几个字段再作一些解释。
以下参数都是对于Willing-to-wait模式的latch而言的,no-wait模式的latch获得情况统计值则在IMMEDIATE_GETS和IMMEDIATE_MISSES字段中。所有v$latch视图中统计值都是在获得了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。

2 Comments Add yours

  1. ian says:

    如上所示,只要曾经MISS过,但MISSES<>SPIN_GETS,那么必然意味着会有SLEEPS出现。SLEEPS之后,就不再累加本次的SPIN_GETS,因此所有的SPIN_GETS值才会都小于MISSES。

    请问这个怎么理解?除去misses后直接sleeps的情况,misses为什么会不等于spin_gets呢

  2. Kamus says:

    @ian
    MISSES=SPIN_GETS+SLEEPS(基本上如此)
    进入sleep以后,仍然会累加MISSES,但是已经不再累加SPIN_GETS。

Leave a Reply

Your email address will not be published. Required fields are marked *