作者:dbtan |【转载时请以超链接形式标明文章出处作者信息】


Shared Pool 的转储与分析:

使用如下命令可以对共享池Library Cache信息进行转储分析:

ALTER SESSION SET EVENTS 'immediate trace name LIBRARY_CACHE level LL';

其中LL代表Level级别,对于9.2.0及以后版本,不同Level含义如下:

·Level=1,转储Library Cache统计信息;
·Level=2,转储Hash Table概要;
·Level=4,转储Library Cache对象,只包含基本信息;
·Level=8,转储Library Cache对象,包含详细信息(如:child references、pin waiters等);
·Level=16,增加heap sizes信息;
·Level=32,增加heap信息。

Library Cache由一个Hash表组成,而Hash表是一个由Hash Buckets组成的数组,每个Hash Bucket都包含Library Cache Handle的一个双向链表。Library Cache Handle指向Library Cache Object和一个引用列表。Library Cache对象进一步分为依赖表、子表和授权表等。

通过以下命令对Library Cache进行转储:

alter session set events 'immediate trace name LIBRARY_CACHE level 4';

接下来进一步讨论一下Shared Pool的内容存储。先进行相应的查询,获得测试数据:

sys@NEI> conn tq/tq
Connected.
tq@NEI> create table emp as select * from scott.emp;
Table created.
tq@NEI> conn / as sysdba
Connected.
tq@NEI> startup force   
sys@NEI> conn scott/tiger
Connected.
scott@NEI> select * from emp;
scott@NEI> conn tq/tq
Connected.
tq@NEI> select * from emp;

tq@NEI> col sql_text for a30
tq@NEI> select sql_text,version_count,hash_value,to_char(hash_value,'xxxxxxxxxx') HEX,address
  2  from v$sqlarea where sql_text like 'select * from emp%';
SQL_TEXT                       VERSION_COUNT HASH_VALUE HEX         ADDRESS
------------------------------ ------------- ---------- ----------- --------
select * from emp                          2 1745700775    680d47a7 43A673D0

tq@NEI> select sql_text,username,address,hash_value,to_char(hash_value,'xxxxxxxxxx') HEX_HASH_VALUE,
  2  child_number,child_latch
  3  from v$sql a,dba_users b
  4  where a.parsing_user_id=b.user_id and sql_text like 'select * from emp%';
SQL_TEXT                       USERNAME   ADDRESS  HASH_VALUE HEX_HASH_VA CHILD_NUMBER CHILD_LATCH
------------------------------ ---------- -------- ---------- ----------- ------------ -----------
select * from emp              TQ         43A673D0 1745700775    680d47a7            1           1
select * from emp              SCOTT      43A673D0 1745700775    680d47a7            0           1

这里可以看出v$sqlarea和v$sql两个视图的不同之处,v$sql中为每一条SQL保留一个条目,而v$sqlarea中根据sql_text进行group by,通过version_count计算子指针的个数。

在以上两次查询中,两条SQL语句因为其代码完全相同,所以其ADDRESS、HASH_VALUE也完全相同。这就意味着,这两条语句在共享池中的存储位置是相同的(尽管其执行计划可能不同),代码得以共享。在SQL解析过程中,Oracle将SQL文本转换为相应的ASCII数值,然后根据数值通过Hash函数计算其HASH_VALUE,再通过HASH_VALUE在Shared Pool中寻找是否存在相同的SQL语句,如果存在则进入下一步骤;如果不存在则尝试获取Shared Pool Latch,请求内存,存储该SQL代码。

在这里有一个问题需要说明一下,因为大小写字母ASCII值是不同的,所以Oracle会把大小写不同的代码作为不同的SQL来处理。看一下测试:

tq@NEI> select * from scott.dept;
    DEPTNO DNAME          LOC
---------- -------------- -------------
        10 ACCOUNTING     NEW YORK
        20 RESEARCH       DALLAS
        30 SALES          CHICAGO
        40 OPERATIONS     BOSTON

tq@NEI> select * from scott.DEPT;
    DEPTNO DNAME          LOC
---------- -------------- -------------
        10 ACCOUNTING     NEW YORK
        20 RESEARCH       DALLAS
        30 SALES          CHICAGO
        40 OPERATIONS     BOSTON

tq@NEI> select sql_text,hash_value from v$sql where sql_text like 'select * from scott%';
SQL_TEXT                       HASH_VALUE
------------------------------ ----------
select * from scott.DEPT       3411718958
select * from scott.dept        911793802

注意到以上的输出,仅仅是大小写的不同使得原本相同的SQL语句变成了两条“不同的代码”,所以从这里可以看出,SQL的规范编写非常重要。

SQL解析首先要进行的是语法解析,语法无误后进行下一个步骤,进行语义分析,在此步骤中,Oracle需要验证对象是否存在、相关用户是否具有权限、引用的是否是相同的对象。

对于先前的查询,实际上emp表来自不同的用户,那么SQL的执行计划也就不同了(当然影响SQL执行计划的因素还有很多,包括优化器模式等),通过对象依赖关系可以看到这个不同:

tq@NEI> col SQL_TEXT for a30
tq@NEI> col TO_OWNER for a10
tq@NEI> col TO_NAME for a10
tq@NEI> select a.*,to_char(to_hash,'xxxxxxxxxx') Hex_HASH_VALUE
  2  from v$object_dependency a where to_name='EMP';
FROM_ADD  FROM_HASH TO_OWNER   TO_NAME    TO_ADDRE    TO_HASH    TO_TYPE HEX_HASH_VA
-------- ---------- ---------- ---------- -------- ---------- ---------- -----------
43A5FD00 3494121331 TQ         EMP        43A604F8  127687888          2     79c5cd0
43A673D0 1745700775 SCOTT      EMP        43A67194 3371416969          2    c8f3bd89

回忆一下前面介绍过的Buffer Cache的管理,其中Bucket→BH(buffer header)→Buffer的管理方式与以上Library Cache的管理原理完全类似。

Library Cache Handle可以被看作库缓存对象的概要信息,Handle上存有指针指向Library Cache Object,Handle中还包含对象名、namespace、时间戳、引用列表、锁定对象及pin对象列表等信息。这里还需要说明的是Handle上的指针指向的是Library Cache Object的Heap 0,库缓存对象可能占用多个内存Heap,Heap 0则记录了控制信息,包括对象类型、对象依赖表、指向其他Heap的指针等。

至于Dictionary Cache信息则可以通过如下命令进行转储:

ALTER SESSION SET EVENTS 'immediate trace name row_cache level N';

这里的N可以取的值如下:

·1,转储dictionary cache的统计信息;
·2,转储hash表的汇总信息;
·8,转储dictionary cache中的对象的结构信息。

- The End -