Latch cache buffers chains大约是Oracle中child latch数量最多,使用最为频繁的闩锁了。其子闩总数受到初始化参数(8i中的db_block_buffers/4)的影响,Oracle中有大量kernel函数有机会接手持有cache buffer chains latch:
col parent_name for a25
col location for a40
SELECT t1.ksllasnam "parent_name",
t2.ksllwnam "location"
FROM x$ksllw t2, x$kslwsc t1
WHERE t2.indx = t1.indx
AND ksllasnam = 'cache buffers chains';
parent_name location
------------------------- ----------------------------------------
cache buffers chains kcbw_activate_granule
cache buffers chains kcbw_first_buffer_free
cache buffers chains kcbwxb
cache buffers chains kcbw_examine_granule
cache buffers chains kcbw_next_free
cache buffers chains kcbw_first_buffer_free_2
cache buffers chains kcbbckb
cache buffers chains kcbbioe
cache buffers chains kcbbic1
cache buffers chains kcbbcwd
cache buffers chains kcbbxsv
parent_name location
------------------------- ----------------------------------------
cache buffers chains kcbbwdb
cache buffers chains kcbbic2
cache buffers chains kcbkzs
cache buffers chains kcbrmf2so
cache buffers chains kcbget: exchange rls
cache buffers chains kcbralloc
cache buffers chains kcbgcur: deadlock
cache buffers chains kcbgcur: buf pinned
cache buffers chains kcbgtcr
cache buffers chains kcbchg: no fast path
cache buffers chains kcbchg: apply change
parent_name location
------------------------- ----------------------------------------
cache buffers chains kcbrra: buf exists
cache buffers chains kcbrra: update buf flags
cache buffers chains kcbema: find buf
cache buffers chains kcbtema: find buf
cache buffers chains kcbget: prewarm wait
cache buffers chains kcbrfrebuf
cache buffers chains kcbsod1
cache buffers chains kcbrbrl
cache buffers chains kcbgcur: kslbegin
cache buffers chains kcbgtcr: kslbegin shared
cache buffers chains kcbrls: kslbegin
parent_name location
------------------------- ----------------------------------------
cache buffers chains kcbchg: kslbegin: bufs not pinned
cache buffers chains kcbchg: kslbegin: call CR func
cache buffers chains kcbnlc
cache buffers chains kcbget: exchange
cache buffers chains kcbget: pin buffer
cache buffers chains kcbnew: new latch again
cache buffers chains kcbgkcbcr
cache buffers chains kcbget: in cur_read
cache buffers chains kcbesc: escalate
cache buffers chains kcblbi
cache buffers chains kcbcge
parent_name location
------------------------- ----------------------------------------
cache buffers chains kcbfrl
cache buffers chains kcbzsc
cache buffers chains kcbibr
cache buffers chains kcbnew_1
cache buffers chains kcbema
cache buffers chains kcbsrbd
cache buffers chains kcbso1: set no access
cache buffers chains kcbtema
cache buffers chains kcbso1: in done_clr
cache buffers chains kcbsod2
cache buffers chains kcbzcg
parent_name location
------------------------- ----------------------------------------
cache buffers chains kcbzre1
cache buffers chains kcbrlb1
cache buffers chains kcbchkrsod
cache buffers chains kcbxbh
cache buffers chains kcbzsck
cache buffers chains kcbgtcr: fast path
cache buffers chains kcbgtcr: kslbegin excl
cache buffers chains kcbgtcrf
cache buffers chains kcbfdgd
cache buffers chains kcbdng
cache buffers chains kcbbufaddr2hdr
parent_name location
------------------------- ----------------------------------------
cache buffers chains kcbo_ivd_process
cache buffers chains kcbo_write_process
cache buffers chains kcbo_exam_buf
cache buffers chains kcb_pre_apply: kcbhq61
cache buffers chains kcb_post_apply: kcbhq62
cache buffers chains kcb_post_apply: kcbhq63
cache buffers chains kcbnew : new esc failed
cache buffers chains kcbesc : escalate failed
cache buffers chains kcb_private_owner
cache buffers chains kcb_is_private
cache buffers chains kcb_unprivatize
parent_name location
------------------------- ----------------------------------------
cache buffers chains kcb_restore_block_headers
cache buffers chains kcb_flush_undo_buffers
cache buffers chains kcbgcur - DEADL
cache buffers chains kcbtbd
cache buffers chains kcbzwc
cache buffers chains kcbzwx
cache buffers chains kcbrmflx
cache buffers chains kcbzwb
cache buffers chains kcbzgb: get latch after post
cache buffers chains kcbzgb: scan from tail. nowait
cache buffers chains kcbzgb: exit_loop
parent_name location
------------------------- ----------------------------------------
cache buffers chains kcbzib: multi-block read: nowait
cache buffers chains kcbzib: finish free bufs
cache buffers chains kcbzcb
cache buffers chains kcbzdh
cache buffers chains kcbdpr
cache buffers chains kcbcxx
cache buffers chains kcbzrn
cache buffers chains kcbdpd: for specific dba
cache buffers chains kcbdpd: dump all buffers
cache buffers chains kcbzib: exchange rls
cache buffers chains kcbzpnd: dump buffers
parent_name location
------------------------- ----------------------------------------
cache buffers chains kcbzhngcbk1: get hash chain latch no wai
t
cache buffers chains kcbo_cxx
cache buffers chains kcbz_check_obj_reuse_sanity
cache buffers chains kcbzib_grlk
cache buffers chains kcbz_force_maps
cache buffers chains kcbrldflx: recover in-flux bufs
cache buffers chains kcbra1fbuf: recover in-flux bufs
cache buffers chains kcbrafb: flashback bufs:1
cache buffers chains kcbrafb: flashback bufs:2
parent_name location
------------------------- ----------------------------------------
cache buffers chains kcbr_media_apply: find buffer
cache buffers chains kcbr_issue_read: alloc buffer
cache buffers chains kcbr_issue_read: retry alloc
cache buffers chains kcbr_validate_read: mark corrupt
cache buffers chains kcbr_apply_change: after apply
cache buffers chains kcbr_mapply_change
cache buffers chains kcbr_mrcv_clear_fgda
cache buffers chains kclwlr
cache buffers chains kclebs_1
cache buffers chains kclcls
cache buffers chains kclcsr_1
parent_name location
------------------------- ----------------------------------------
cache buffers chains kclpred
cache buffers chains kclcls_1
cache buffers chains kclple_1
cache buffers chains kclple_2
cache buffers chains kclcls_2
cache buffers chains kcllwr
cache buffers chains kclwcrs
cache buffers chains kclcrs_1
cache buffers chains kclcsr
cache buffers chains kclrls
cache buffers chains kclwcrs_1
parent_name location
------------------------- ----------------------------------------
cache buffers chains kclfbst_1
cache buffers chains kclpdc_1
cache buffers chains kclwcrs_2
cache buffers chains kclwcrs_3
cache buffers chains kclfpdb
cache buffers chains kclfpdb_2
cache buffers chains kclpdc_2
cache buffers chains kcllkopb
cache buffers chains kclgrantlk
cache buffers chains kclwrt
cache buffers chains kcllkopb_1
parent_name location
------------------------- ----------------------------------------
cache buffers chains kclwcrs_4
cache buffers chains kcllkopb_2
cache buffers chains kclcls_4
cache buffers chains kclpred_1
cache buffers chains kclrclr_2
cache buffers chains kclrecbst
cache buffers chains kclgrantlk_1
cache buffers chains kclcls_5
cache buffers chains kclrwrite_1
cache buffers chains kclrwrite_2
cache buffers chains kclcopy
parent_name location
------------------------- ----------------------------------------
cache buffers chains kclswrite
cache buffers chains kclchash
cache buffers chains kclcfusion
cache buffers chains kclfchk_1
cache buffers chains kclcfusion_1
cache buffers chains kclblkdone
cache buffers chains kclcfusion_2
cache buffers chains kclrenounce
cache buffers chains kclbla
cache buffers chains kclpto_1
cache buffers chains kclgrantlk_2
parent_name location
------------------------- ----------------------------------------
cache buffers chains kclcomplete
cache buffers chains kclshrshr
cache buffers chains kclclaim
cache buffers chains kclhngcbk1
cache buffers chains kclblkdone_1
cache buffers chains kclgvlk
cache buffers chains kclblkdone_2
cache buffers chains kclcclaim
cache buffers chains kclrechk_1
cache buffers chains kclrechk_2
cache buffers chains kclbr
parent_name location
------------------------- ----------------------------------------
cache buffers chains kclpto
cache buffers chains kclpdcl
cache buffers chains kclpdc_3
cache buffers chains kclpdc_4
cache buffers chains kclgcr_1
cache buffers chains kclcls_6
cache buffers chains kclevict
cache buffers chains kcldle
cache buffers chains kclrcopy
cache buffers chains kclenter
cache buffers chains kclrbast
parent_name location
------------------------- ----------------------------------------
cache buffers chains kclexpand
cache buffers chains kclcls_3
cache buffers chains kclverify
cache buffers chains kclaffinity
cache buffers chains kclassert
cache buffers chains kclobj
cache buffers chains kclobj_1
cache buffers chains kclobj_2
cache buffers chains kclgclk
cache buffers chains kclwcrs_5
cache buffers chains kclscrs
parent_name location
------------------------- ----------------------------------------
cache buffers chains kclstalepi
cache buffers chains kclstalepi_1
cache buffers chains kclstalepi_2
cache buffers chains kclgvlk_1
cache buffers chains kclgclk_1
cache buffers chains kclgclk_2
cache buffers chains kclcsr_2
cache buffers chains kcbvm
204 rows selected.
我们一般认为Latch结构是Mostly exclusive access的,也就是极少会有共享访问闩的机会。但Oracle一般对外宣称读取数据时服务进程是以共享模式使用cache buffers chains闩,这就造成了许多人误以为读读是不会出现latch: cache buffers chains争用的。
但是实际上查询语句大部分情况下仍需要以exclusive模式持有该类子闩(有时会以SHARED模式持有,这取决于读取时是使用kcbgtcr: kslbegin shared还是kcbgtcr: kslbegin excl;kcbgtcr是Oracle rdbms中重要的获取一致性读的函数,其含义为Kernal Cache Buffer GeT Cosistents Read,显然该函数存在两种获取cache buffers chains的方式即kslbegin shared和excl。与之相对应的是kcbgcur: kslbegin,kcbgcur的含义为Kernel Cache Buffer Get Current,该函数用以获取当前块以便修改,也就是"写";很显然kcbgcur: kslbegin函数只有以excl排他方式持有child cache buffers chains latch的必要),原因在于虽然是查询语句但同样需要修改buffer header结构,譬如修改tch抢手度、holder list的hash变量us_nxt、us_prv以及waiter list的hash变量wa_prv、wa_nxt等。换而言之读读是会引起Latch free:cache buffers chains等待的,而非许多人认为的仅有读写、写写会导致缓存链闩争用。
这个问题我们再用实验证明一遍:
SQL> drop table maclean;
drop table maclean
*
ERROR at line 1:
ORA-00942: table or view does not exist
SQL> create table maclean tablespace users as select * from dba_objects;
Table created.
SQL> select count(*) from maclean;
COUNT(*)
----------
51944
SQL> /
COUNT(*)
----------
51944
SQL> /
COUNT(*)
----------
51944
SQL> select spid from v$process where addr =(select paddr from v$session where sid=(select distinct sid from v$mystat));
SPID
------------
6023
另开一个命令行窗口:
[maclean@rh2 ~]$ gdb $ORACLE_HOME/bin/oracle 6023
GNU gdb (GDB) Red Hat Enterprise Linux (7.0.1-23.el5)
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
...
Reading symbols from /s01/10gdb/bin/oracle...(no debugging symbols found)...done.
Attaching to program: /s01/10gdb/bin/oracle, process 6023
Reading symbols from /s01/10gdb/lib/libskgxp10.so...(no debugging symbols found)...done.
Loaded symbols for /s01/10gdb/lib/libskgxp10.so
Reading symbols from /s01/10gdb/lib/libhasgen10.so...(no debugging symbols found)...done.
Loaded symbols for /s01/10gdb/lib/libhasgen10.so
Reading symbols from /s01/10gdb/lib/libskgxn2.so...(no debugging symbols found)...done.
Loaded symbols for /s01/10gdb/lib/libskgxn2.so
Reading symbols from /s01/10gdb/lib/libocr10.so...(no debugging symbols found)...done.
Loaded symbols for /s01/10gdb/lib/libocr10.so
Reading symbols from /s01/10gdb/lib/libocrb10.so...(no debugging symbols found)...done.
Loaded symbols for /s01/10gdb/lib/libocrb10.so
Reading symbols from /s01/10gdb/lib/libocrutl10.so...(no debugging symbols found)...done.
Loaded symbols for /s01/10gdb/lib/libocrutl10.so
Reading symbols from /s01/10gdb/lib/libjox10.so...(no debugging symbols found)...done.
Loaded symbols for /s01/10gdb/lib/libjox10.so
Reading symbols from /s01/10gdb/lib/libclsra10.so...(no debugging symbols found)...done.
Loaded symbols for /s01/10gdb/lib/libclsra10.so
Reading symbols from /s01/10gdb/lib/libdbcfg10.so...(no debugging symbols found)...done.
Loaded symbols for /s01/10gdb/lib/libdbcfg10.so
Reading symbols from /s01/10gdb/lib/libnnz10.so...(no debugging symbols found)...done.
Loaded symbols for /s01/10gdb/lib/libnnz10.so
Reading symbols from /usr/lib64/libaio.so.1...(no debugging symbols found)...done.
Loaded symbols for /usr/lib64/libaio.so.1
Reading symbols from /lib64/libdl.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib64/libdl.so.2
Reading symbols from /lib64/libm.so.6...(no debugging symbols found)...done.
Loaded symbols for /lib64/libm.so.6
Reading symbols from /lib64/libpthread.so.0...(no debugging symbols found)...done.
[Thread debugging using libthread_db enabled]
Loaded symbols for /lib64/libpthread.so.0
Reading symbols from /lib64/libnsl.so.1...(no debugging symbols found)...done.
Loaded symbols for /lib64/libnsl.so.1
Reading symbols from /lib64/libc.so.6...(no debugging symbols found)...done.
Loaded symbols for /lib64/libc.so.6
Reading symbols from /lib64/ld-linux-x86-64.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib64/ld-linux-x86-64.so.2
0x00000039f280d8e0 in __read_nocancel () from /lib64/libpthread.so.0
(gdb) break kcbgtcr
Breakpoint 1 at 0x108c72c
回到原sqlplus窗口再次执行查询语句,会hang住:
SQL> select count(*) from maclean;
在gdb窗口:
(gdb) break kslfre
Breakpoint 2 at 0x7a133c
Breakpoint 1, 0x000000000108c72c in kcbgtcr ()
(gdb) c
Continuing.
Breakpoint 1, 0x000000000108c72c in kcbgtcr ()
(gdb) c
Continuing.
Breakpoint 1, 0x000000000108c72c in kcbgtcr ()
(gdb) c
Continuing.
Breakpoint 2, 0x00000000007a133c in kslfre ()
(gdb) c
Continuing.
多次continue直到出现kslfre内核函数,开一个新的sqlplus窗口:
SQL> set autotrace on;
SQL> select count(*) from v$latchholder;
COUNT(*)
----------
3
Execution Plan
----------------------------------------------------------
Plan hash value: 1575818826
--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 13 | 0 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 13 | | |
|* 2 | FIXED TABLE FULL| X$KSUPRLAT | 1 | 13 | 0 (0)| 00:00:01 |
--------------------------------------------------------------------------------
v$latchholder的数据来源于X$KSUPRLAT内部视图,因为v$latchholder不带mode字段,所以我们直接观察X$KSUPRLAT
SQL> select KSUPRLAT "address",KSUPRLNM "name",KSUPRLMD "mode" from X$KSUPRLAT;
address name mode
---------------- ------------------------- ---------------
00000000FCE40040 cache buffers chains EXCLUSIVE
00000000FA696978 simulator lru latch EXCLUSIVE
00000000FA6CDCE0 simulator hash latch EXCLUSIVE
/* 可以看到即便是查询语句也是以EXCLUSIVE mode持有child cache buffers chains latch */
(gdb) quit
A debugging session is active.
Inferior 1 [process 6235] will be detached.
Quit anyway? (y or n) y
Detaching from program: /s01/10gdb/bin/oracle, process 6235
/* 可以通过以下statistics可以看到以上读取为纯粹的逻辑读,没有物理读取的部分干扰*/
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
719 consistent gets
0 physical reads
0 redo size
517 bytes sent via SQL*Net to client
492 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed