一,library cache的结构
Library cache是shared pool中最重要的一部分,主要存放sql(parent cursor、child cursor)和plsql(procedure、function、package)对象的信息,以及这些对象所依赖的table、index等。
1.hash bucket
Library cache由hash bucket来管理,hash bucket由多个object handle组成。
2.object handle
Object handle存放了对象的name、namespace及相关信息(对象是否只读,是本机的还是远端的等),也存放了当前正在lock和pin以及正在等待lock和pin该对象的用户的列表等。
3.library cache objects
Library cache objects由多个独立的data heap组成,object handle存放指向第一个data heap(heap 0)的指针,heap 0存放指向其他data heap的指针。任何对象都有heap 0,至于其它的heap则由对象的类型决定,比如sql cursor具有heap 1和heap 6,plsql程序包则具有heap 1、2、3、4。那么,对于sql cursor来说,heap 0就存放指向heap 1和heap 6的指针。
当进程需要寻找一个对象时,library cache manager就会使用hash算法定位到相应的object handle。如果object handle还在,但是相关的object heap已经被刷出内存,此时object heap就要被重新reload(v$librarycache.reloads);如果,进程发现相关object的定义已经被更改(v$librarycache.invalidations),此时进程就要重新解析相关对象。
4.data heap
Library cache的全局结构如下图:
4.1 data heap 0
如图,Heap 0包含以下信息:
– Type
Objects are grouped in namespaces according to their type.
Each object can only be of one type.
All the objects of the same type are in the same namespace.
A namespace may be used by more than one type.
The most important namespace is called cursor(CRSR) and houses the shared SQL cursors.
– Name
Library cache object names have three parts:
– Name of schema
– Name of object
- For shared cursors (SQL statements or anonymous PL/SQL blocks) the name is the entire text string that makes the cursor itself. For example, select * from employees. Note that this is different from select * from hr.employees or even select* from EMPLOYEES. Every character, including the case, is taken into consideration.
- For the rest of the objects (tables, views, indexes, and so on) the name is the one given to the object at creation time.
通过dump文件来看,sql text存放在handle下面,不是放在heap 0里面的。不知道此处的entire text string指的是什么???(望广大网友帮忙澄清一下)
– Name of database link (remote objects only)
The format used is SCHEMA.NAME@DBLINK.
For example, [email protected]
Child cursor没有name,通过parent cursor来访问。
– Flags
Public flags:
– Are not protected by pins or latches
– Indicate in detail the type of the object
Status flags:
– Are protected by pins
– Indicate whether the object is being created/dropped/altered/updated
Special status flags:
– Are protected by the library cache latch
– Are related to object validity and authorization
– Tables
Dependency table
Child table
只有cursor才有子对象,一个sql语句至少有一个parent cursor(heap 0)和一个child cursor(heap 1、heap 6),但是出于某种原因,比如1,sql语句的对象是不同用户下的同名对象;2,sql语句使用了不同类型的绑定变量;3,执行sql语句的会话的优化器模式不同等。就会出现一个parent cursor对应多个child cursor的情况(v$sqlarea.version_count)。Parent cursor对应的所有child cursor的指针都存放在child table里面。Child cursor除了没有name,其结构和parent cursor一样,parent cursor也只是存放指向child cursor的指针,而child cursor存放指向其依赖对象的指针。
Translation table
Authorization table
Access table
Read-only dependency table
Schema name table
– Data blocks
The remainder of an object’s data is stored in other independent data heaps.
The object structure contains an array of data block structures.
The data block structures have a pointer to a different data heap.
An object structure has room for 16 data block structures but not all of them are in use.
一个对象由多个不同的data heap组成,object handle存放指向 data heap0的指针,而data heap0中的data blocks就是用来存放指向其他data heap的指针
4.2 other data heap
a SQL cursor has heaps 1 and 6, while a PL/SQL procedure may have heaps 1, 2, 3,and 4.
Heap 0 (Object): Stores the object structure
Heap 1 (Source): Stored the source code for a PL/SQL object
Heap 2 (Diana) : Contains the DIANA (Parse tree metadata) for a PL/SQL object
Heap 3 (Pcode): Stores the pseudocode for a PL/SQL object
Heap 4 (Mcode): Machine-dependent pseudocode for a PL/SQL object
Heap 5 (Errors): Stores compilation errors
Heap 6 (SQL Context): Contains context information for a shared cursor object
Heap 7: Free (not used)
Heaps 8–11: Subordinate heaps that are used for different purposes depending on the object
二、Sql对象
1.父游标
每一个sql语句都包含一个父游标和一个或多个子游标。
父游标由KGLHD - Handle structure、KGLOB - Object structure、KGLNA - Name structure组成。
Objects are joined with their handles in X$KGLOB.Julian Dyke的图如下:
SQL> conn test/test
Connected.
SQL> select count(*) from tt;
COUNT(*)
----------
3318546
SQL> select sql_id,address,hash_value,sql_text from v$sql where sql_text like 'select count(*) from tt';
SQL_ID ADDRESS HASH_VALUE SQL_TEXT
------------- ---------------- ---------- ------------------------
cm6stbx539mcz 0000000393558EE8 1244974495 select count(*) from tt
SQL> select * from x$kglna where kglnahsh=1244974495;
ADDR INDX INST_ID KGLHDADR KGLNAHSH KGLOBOCT KGLNASQLID PIECE NAME
---------------- ---------- ---------- ---------------- ---------- ---------- ------------- ---------- ------------------------
FFFFFD7FFDA53A88 0 1 0000000393558EE8 1244974495 3 cm6stbx539mcz 0 select count(*) from tt
由此可见,kglna描述的是sql_text的相关信息。
V$sqlarea一行代表一个父游标。
2.子游标
子游标和父游标有着类似的结构,也都包含Handle structure、Object structure,子游标还包含sql语句的执行计划等,此处,heap6存放的就是sql语句的执行计划。
再用不同的用户执行select count(*) from tt,使得生成一个新的child cursor:
SQL> select kglhdadr,kglhdpar,kglobsta,kglnaobj from x$kglob where kglnahsh=1244974495;
KGLHDADR KGLHDPAR (parent) KGLOBSTA KGLNAOBJ
---------------- ---------------- ---------- ------------------------
0000000393557FB8 0000000393558EE8 1 select count(*) from tt
0000000393558EE8 0000000393558EE8 1 select count(*) from tt
第一行是子游标,第二行是父游标(kglhdadr=kglhdpar)。
V$sql一行代表一个子游标。由此可见,v$sqlarea和v$sql的区别是v$sqlarea是在v$sql的基础上以相同的sql_text做的group by。
3.造成cursor不共享的原因
造成parent cursor不共享的原因是sql语句的写法不同,比如,关键字的大小写不同等。
造成child cursor不共享的原因是1,系统或会话参数不同。2,同名对象但不属于同一用户。3,绑定变量类型不同。4,nls参数不同
V$sql_shared_cursor视图可以查看cursor不共享的原因。如果一个parent cursor存在多个child cursor,那么在此视图中,第一个child cursor的boolean值为N。
以下为优化器环境不同造成的cursor不共享:
SQL> show parameter optimizer
NAME TYPE VALUE
------------------------------------ ----------- ---------
optimizer_dynamic_sampling integer 2
optimizer_features_enable string 10.2.0.4
optimizer_index_caching integer 0
optimizer_index_cost_adj integer 100
optimizer_mode string CHOOSE
optimizer_secure_view_merging boolean TRUE
SQL> select count(*) from test.tt;
COUNT(*)
----------
3318546
SQL> alter session set optimizer_mode=all_rows;
Session altered.
SQL> select count(*) from test.tt;
COUNT(*)
----------
3318546
SQL> select address,child_address,sql_text from v$sql where sql_text like 'select count(*) from test.tt';
ADDRESS CHILD_ADDRESS SQL_TEXT
---------------- ---------------- ------------------------------
00000003935DF758 000000039384BAA0 select count(*) from test.tt
00000003935DF758 0000000393272008 select count(*) from test.tt
SQL> select kglhdadr,kglhdpar,kglobsta,kglnaobj from x$kglob where kglnahsh=458373349;
KGLHDADR KGLHDPAR KGLOBSTA KGLNAOBJ
---------------- ---------------- ---------- ---------------------------
000000039384BAA0 00000003935DF758 1 select count(*) from test.tt
0000000393272008 00000003935DF758 1 select count(*) from test.tt
00000003935DF758 00000003935DF758 1 select count(*) from test.tt
SQL> select child_number,child_address,optimizer_mode_mismatch from v$sql_shared_cursor where address='00000003935DF758';
CHILD_NUMBER CHILD_ADDRESS OPTIMIZER_MODE_MISMATCH
------------ ---------------- -----------------------
0 000000039384BAA0 N
1 0000000393272008 Y
还有许多其它因素造成cursor的不共享。
4.library cache dump
使用以下命令dump library cache
ALTER SESSION SET EVENTS 'IMMEDIATE TRACE NAME LIBRARY_CACHE LEVEL n';
where <n> specifies information to be included
1 - include library cache statistics
2 - include library cache hash table
4 - include library cache handles and objects
8 - include dependencies, read-only dependencies, accesses, authorizations, translations, schemas and data blocks
16 - include sizes for data blocks
32 - include heap dumps for data blocks
SQL> conn test/test
Connected.
SQL> select count(*) from t;
COUNT(*)
----------
1
SQL> alter session set tracefile_identifier=111;
Session altered.
SQL> alter session set events 'immediate trace name library_cache level 8';
Session altered.
SQL> select hash_value,address,child_address,sql_text from v$sql where sql_text like 'select count(*) from t';
HASH_VALUE ADDRESS CHILD_ADDRESS SQL_TEXT
---------- ---------------- ---------------- --------------------------------------------------------------------------------
2763161912 0000000393B710A8 0000000393B71590 select count(*) from t
2763161912 0000000393B710A8 0000000393D45D20 select count(*) from t
根据hash_value在dump文件中寻找
SQL> select to_char(2763161912,'xxxxxxxxxxxxxxx') from dual;
TO_CHAR(27631619
----------------
a4b28138
Parent cursor:
BUCKET 33080:
LIBRARY OBJECT HANDLE: handle=393b710a8 mtx=393b711d8(2) cdp=2
name=select count(*) from t ----验证了sql_text是放在handle下面的
hash=10bef657c8a7ea0dcf7ff45fa4b28138 timestamp=12-04-2013 15:01:12
namespace=CRSR flags=RON/KGHP/TIM/PN0/SML/KST/DBN/MTX/[120100d0]
kkkk-dddd-llll=0000-0001-0001 lock=0 pin=0 latch#=1 hpc=0000 hlc=0000
lwt=393b71150[393b71150,393b71150] ltm=393b71160[393b71160,393b71160]
pwt=393b71118[393b71118,393b71118] ptm=393b71128[393b71128,393b71128]
ref=393b71180[393b71180,393b71180] lnd=393b71198[393b71198,393b71198]
LIBRARY OBJECT: object=393b70a38
type=CRSR flags=EXS[0001] pflags=[0000] status=VALD load=0
CHILDREN: size=16 ----存放的是child cursor的信息。Child table初始大小为16,也就是说初始可以存放
child# table reference handle 16个子游标的信息,但为了性能考虑最好不要超过16个。
------ -------- --------- --------
0 393b70500 393b70170 393b71590
1 393b70500 393b703f0 393d45d20 ----找寻此handle的child cursor
DATA BLOCKS:
data# heap pointer status pins change whr
----- -------- -------- --------- ---- ------ ---
0 393b70fe8 393b70b50 I/P/A/-/- 0 NONE 00
BUCKET 33080 total object count=1
Child cursor:
LIBRARY OBJECT HANDLE: handle=393d45d20 mtx=393d45e50(0) cdp=0
namespace=CRSR flags=RON/KGHP/PN0/EXP/[10010100] ----child cursor没有name
kkkk-dddd-llll=0000-0001-0001 lock=0 pin=0 latch#=1 hpc=fffc hlc=fffc
lwt=393d45dc8[393d45dc8,393d45dc8] ltm=393d45dd8[393d45dd8,393d45dd8]
pwt=393d45d90[393d45d90,393d45d90] ptm=393d45da0[393d45da0,393d45da0]
ref=393d45df8[393b703f0,393b703f0] lnd=393d45e10[393d45e10,393d45e10]
LIBRARY OBJECT: object=393d45850
type=CRSR flags=EXS/RIV[0201] pflags=[0000] status=VALD load=0
DEPENDENCIES: count=1 size=16
dependency# table reference handle position flags
----------- -------- --------- -------- -------- -------------------
0 393d44318 393d44058 393d4c0b8 21 DEP[01] ----找寻cursor的依赖表T
AUTHORIZATIONS: count=1 size=16 minimum entrysize=16
00000000 3a000000 00020000 00000000
ACCESSES: count=1 size=16
dependency# types
----------- -----
0 0009
TRANSLATIONS: count=1 size=16
original final
-------- --------
393d4c0b8 393d4c0b8
DATA BLOCKS:
data# heap pointer status pins change whr
----- -------- -------- --------- ---- ------ ---
0 393d45c60 393d45968 I/-/A/-/- 0 NONE 00
6 393b70290 393d450b8 I/-/A/-/E 0 NONE 00 ----heap 6保存的是cursor的执行计划。
Dependency table:
BUCKET 109969:
LIBRARY OBJECT HANDLE: handle=393d4c0b8 mtx=393d4c1e8(0) cdp=0
name=TEST.T
hash=776506cbf60f0b9d0c63341052d5ad91 timestamp=12-04-2013 15:01:56
namespace=TABL flags=KGHP/TIM/SML/[02000000]
kkkk-dddd-llll=0000-0741-0741 lock=0 pin=0 latch#=1 hpc=0004 hlc=0004
lwt=393d4c160[393d4c160,393d4c160] ltm=393d4c170[393d4c170,393d4c170]
pwt=393d4c128[393d4c128,393d4c128] ptm=393d4c138[393d4c138,393d4c138]
ref=393d4c190[393d4c190,393d4c190] lnd=393d4c1a8[3940dfb20,393d40c00]
LIBRARY OBJECT: object=393d4bbe8
type=TABL flags=EXS/LOC[0005] pflags=[0000] status=VALD load=0
DATA BLOCKS:
data# heap pointer status pins change whr
----- -------- -------- --------- ---- ------ ---
0 393d4bff8 393d4bd40 I/-/A/-/- 0 NONE 00
8 393d4b118 393d4aec0 I/-/A/-/- 0 NONE 00
BUCKET 109969 total object count=1
Parent cursor和child cursor的结构如下: