分类: Oracle
2009-02-03 08:58:05
library cache就是使用多个hash bucket来管理的,其hash算法当然比我们前面列举的要复杂多了。每个hash bucket后面都串连着多个句柄(该句柄叫做library cache object handle),这些句柄描述了library cache里的对象的一些属性,包括名称、标记、指向对象所处的内存地址的指针等。可以用下图一来描述library cache的整体结构。
图三
当一条SQL语句进入library cache的时候,先将SQL文本转化为对应ASCII数值,然后对该这些ASCII数值进行hash函数的运算,传入函数的是SQL语句的名称(name,对于SQL语句来说其name就是SQL语句的文本)以及命名空间(namespace,对于SQL语句来说是“SQL AREA”,表示共享游标。可以从视图v$librarycache里找到所有的namespace)。运用hash函数后得到一个值,该值就是hash bucket的号码,从而该SQL语句被分配到该号的hash bucket里去。实际上,hash bucket就是通过串连起来的对象句柄才体现出来的,它本身是一个逻辑上的概念,是一个逻辑组,而不像对象是一个具体的实体。oracle根据 shared_pool_size所指定的shared pool尺寸自动计算hash buckets的个数,shared pool越大,则可以挂载的对象句柄就越多。
当某个进程需要处理某个对象时,比如处理一条新进入的SQL语句时,它会对该SQL语句应用hash函数算法,以决定其所在的hash bucket的编号,然后进入该hash bucket进行扫描并比较。有可能会发生该对象的句柄存在,但是句柄所指向的对象已经被交换出内存的情况出现。这时对应的对象必须被再次装载(reload)。也可能该对象的句柄都不存在,这时进程必须重新构建一个对象句柄挂到hash bucket上,然后再重新装载对象。SQL语句相关的对象有很多(最直观的就是SQL语句的文本),这些对象都存放在library cache里,它们都通过句柄来访问。可以把library cache理解为一本书,而SQL语句的对象就是书中的页,而句柄就是目录,通过目录可以快速定位到指定内容的页。
对象句柄存放了对象的名称(name)、对象所属的命名空间(namespace)、有关对象的一些标记(比如对象是否为只读、为本地对象还是远程对象、是否被pin在内存中等等)以及有关对象的一些统计信息等。而且,对象句柄中还存放了当前正在lock住和pin住该对象的用户列表、以及当前正在等待 lock和pin该对象的用户列表。对象句柄中存放的最重要的内容就是指向Heap 0对象的指针了。Heap 0用来存放与对象有直接关系的一些信息,比如对象类型、对象相关的表(比如依赖表、子表等)、指向对象的其他数据块的指针(这些数据块指向了实际存放 SQL文本、PL/SQL代码、错误信息等的大内存块,这些大内存块依次叫做Heap 1、2、3、4等)等信息。
Heap是通过调用进程进行分配的,任何对象都具有heap 0,至于还应该分配哪些其他的heap则是由对象的类型决定的,比如SQL游标具有heap 1和 6,而PL/SQL程序包则具有heap 1、2、3和4.按照heap的使用情况,oracle会在SGA(library cache)、PGA或UGA中分配heap,但是heap 0始终都是在library cache中进行分配的。如果所请求的heap已经在SGA中分配了,则不会在PGA中再次分配heap.Heap是由一个或多个chunk组成的,这些 chunk可以是分散的分布在library cache中的,不需要连续分布。
如上图三中所看到的heap 0实际上是指heap 0的句柄,其中包含的对象包括:
1) object type:library cache中的对象类型包括:表、视图、索引、同名词等等。每个对象只能有一个object type,根据object type将对象归类到不同的namespace里。一个object type对应一个namespace,但是一个namespace可能对应多个object type.这样的话,查找一个对象时,只要在该对象所属的namespace中去找就可以了。比较常见的namespace包括:
a) SQL AREA:也可以叫做CRSR,表示shared cursor,存放共享的SQL语句。
b) TABLE/PROCEDURE:存放的object type包括:table、view、sequence、synonym、 procedure的定义、function的定义以及package的定义。
c) BODY:存放procedure的实际代码、function的实际代码以及package的实际代码。
d) TRIGGER:存放的object type为trigger.
e) INDEX:存放的object type为index.
2) object name:对象名称由三部分组成:
a) Schema的名称,对于共享游标(SQL语句或PL/SQL程序块)来说为空。
b) 对象名称。分为两种情况:对于共享游标(SQL语句或PL/SQL程序块)来说,其对象名称就是SQL的语句本身;而对于其他对象(比如表、视图、索引等)就是其在数据字典中的名称。
c) Database link的名称。这是可选的,如果是本地对象,则为空。
这样,对象的名称的格式为:.比如,可以为,也可以为hr.employees等。
3) flags:flags主要用来描述对象是否已经被锁定。对象具有三种类型的flag:
a) public flag:表示对象上没有锁定(pin)或者latch.
b) status flag:表示对象上存在锁定(pin),说明对象正在被创建或删除或修改等。
c) specitial flag:表示对象上存在library cache latch.
4) tables:对每个对象,都会维护以下一串tables中的若干个:
a) dependency table:含有当前对象所依赖的其他对象。比如一个视图可能会依赖其组成的多个表、一个存储过程可能依赖其中所调用的其他存储过程、一个游标可能依赖其中所涉及到的多个表等。Dependency table中的每个条目都指向一块物理内存,该物理内存中含有当前对象所依赖的对象的句柄。
b) child table:含有当前对象的子对象,只有游标具有child table.Child table中的每个条目都指向一个可执行的SQL命令所对应的句柄。
c) translation table:包含当前对象所引用的名称是如何解释为oracle底层对象的名称,只有游标具有translation table.
d) authorization table:包含该对象上所对应的权限,一个条目对应一个权限。
e) access table:对于dependency table中的每一个条目,都会在access table中存在对应的一个或多个条目。比如,假设对象A依赖对象B,那么在A的dependency table和access table中都会存在一个条目指向B.位于access table中的指向B的条目说明了对B具有什么样的访问类型,从而也就说明了用户要执行A则必须具有对B的权限。
f) read-only dependency table:类似于dependency table,但是存放只读的对象。
g) schema name table:包含authorization table中的条目所属的schema.
5) data blocks:对象的其他信息会存放在不同的heap中,为了找到这些heap,会在heap 0中存放多个(最多16个,但是这16个data block不会都用到)data blocks结构,每个data block含有指向这些实际heap内存块的指针。
除了heap 0以外,还有11个heap,根据对象的不同进行分配,并存放了不同的内容:
1) Heap 1:存放PL/SQL对象的源代码。
2) Heap 2:存放PL/SQL对象的解析树,这有个好听的名字: DIANA.
3) Heap 3:存放PL/SQL对象的伪代码。
4) Heap 4:存放PL/SQL对象的基于硬件的伪代码。
5) Heap 5:存放了编译时的错误信息。
6) Heap 6:存放了共享游标对象的SQL文本。
7) Heap 7:可用空间。
8) Heaps 8–11:根据对象的不同而使用的子heap.
我们可以通过查询v$db_object_cache来显示library cache中有哪些对象被缓存,以及这些对象的大小
尺寸。比如,我们可以用下面的SQL语句来显示每个namespace中,大小尺寸排在前3名的对象:
select *
from (select row_number() over(partition by namespace order by sharable_mem desc) size_rank,
namespace,
sharable_mem,
substr(name, 1, 50) name
from v$db_object_cache
order by sharable_mem desc)
where size_rank <= 3
order by namespace, size_rank;