x$bh 每个buffer在x$bh中都存在一条记录,记录了很多信息,包括该buffer缓存的数据块的表空间,数据文件,数据块号等信息。TCH字段代表该buffer被访问的次数。
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
oracle 7之前,shared pool不存在。
oracle引入shared pool是为了实现代码的共享与重用。
字典缓存的内容按行存储(row cache),其他数据通常按buffer存储。
v$librarycache v$rowcache
从11g开始,除了字典缓存和库缓存,shared pool又增加了result cache(查询结果缓存),提升了性能。
可以在服务器端缓存结果集,也可以在客户端缓存结果集。
服务器端result cache memory由两部分组成:SQL Query result cache和PL/SQL Function result cache。
参数result_cache_mode控制服务端结果集缓存的模式。如果模式为MANUAL,需要加hint才会缓存结果集。
v$result_cache_objects v$result_cache_memory v$result_cache_statistics
shared pool通过free list管理内存块(chunk),free的内存块按照不同的size划分到不同的部分(bucket)。
oracle请求shared pool空间时,首先进入相应的bucket查找,找不到的话就转向下一个非空的bucket,获取第一个chunk,分割这个chunk,剩余的部分进入相应的bucket,进一步增加碎片。
随着内存块被不断分割,bucket列表开始变长。
由于不停的分割,每个bucket上的内存块越来越多,越来越碎小。
通常每个bucket上的chunk多于2000个,就被认为是碎片过多。碎片过多,是shared poo性能问题的主要原因。
碎片过多导致搜索free list时间过长。管理和搜索free list需要获得shared pool latch。被长时间占有。
9i之前shared pool latch只有一个。
增加了更多的bucket,并进一步细分bucket,使每个bucket中容纳的chunk数量大大减少,提高了查询效率。
9i开始,shared pool可以被分割为多个子缓冲池。同时提供多个latch。子缓冲池最多有7个。latch也增加到7个。子latch。
子缓冲池的引入虽然使oracle可以管理更大的shared pool,但也可能会导致各分区之间的协调问题,比如某个sub pool被过度使用,但其他sub pool却有很多空间。
从10g开始,允许内存请求在不同subpool之间切换,提高了请求成功的可能。(但问题仍然可能存在)
对单个subpool进行进一步的细分,缺省的会将单个子缓冲池分割为4个子分区进行管理。(可能是因为4颗CPU才分配一个subpool)
测试表明subpool大小为500m可能会带来更好的性能,所以从11g开始每个subpool至少为512M。
x$ksmsp 视图记录shared pool空间分配和使用情况。每行代表一个chunk。
大量硬解析会不断申请分配free的内存,不断产生碎片。
内存碎片增加是共享池性能下降的开始。
library cache由一个hash表组成,hash表是由hash bucket组成的数组。每个hash bucket都是包含library cache handle的双向列表。library cache handle指向library cache对象和一个引用列表。library cache对象进一步分为依赖表、字表和授权表等。
9i——11g v$librarycache 视图
sql解析过程,将sql文本转换成ASCII数值,通过hash函数计算hash值,再通过hash值再shared pool中寻找是否有相同的sql,如果没有则尝试获取shared pool latch,请求内存,存储该代码。
语法解析--------》语义解析(对象是否存在,用户权限,是否引用相同对象)
对比:
bucket——》 BH ——》buffer
bucket——》 library cache handle ——》library cache object等。
shared pool的主要问题就是碎片过多带来的性能影响。
ORA-04031 当尝试在共享池分配大块的连续内存失败(很多时候是由于碎片太多,而非真正的内存不足)时,oracle首先清除共享池中当前没使用的所有对象,是空闲块内存块合并。如果仍然没有足够大的单块内存可以满足需要,则产生ORA-04031错误。
v$sqlarea sql version count, parse_calls , executions
oracle 绑定变量 peeking机制。只在第一次硬解析的时候生效,所以仍然可能存在问题。
8i中cursor_sharing 有两个取值:exact 精确匹配。force 强制使用绑定变量。
9i中cursor_sharing有了第三个参数 similar,指定oracle在存在柱状图时,对于不同的变量值,重新解析。有柱状图的时候,跟exact相同。没柱状图是,跟force相同。
但也可能导致version_count过高的bug。
大量的version_count可能导致数据库产生大量的 cursor:pin S wait on X。
强制刷新缓冲池alter system flush shared_pool
shared_pool_reserved_size 制定了保留的共享池空间,用于满足将来的大的连续的共享池空间请求。
当出现过多碎片,请求大块空间会导致大范围的查找并释放共享池内存来满足请求,由此可能带来较为严重的性能下降。
设置合适的shared_pool_reserved_size 结合shared_pool_reserved_min_alloc参数用来避免由此导致的性能下降。
缺省值 shared_pool * 5%建议10%——20%
v$shared_pool_reserved
dbms_shared_pool.keep
library cache lock 等待事件(handle) 解析锁,比pin更高级别的锁,在对象的handle上获得,pin一个对象之前,必须首先获得该handle的锁定。 null share exclusive。
library cache pin 等待事件(object) 以读取或改变对象内容为目的所加的短时锁, null share exclusive。该等待事件出现时,通常说明该pin被其他用户非兼容模式持有。通常是发生在编译或者重新编译对象时。
shared pool latch和library cache latch是shared pool管理中最重要也是最常见的latch竞争。过度解析容易造成这个问题。
shared pool latch用于共享池中内存空间的分配和回收。
library cache latch用于保护cache在内存中的sql及执行计划等。需要向library cache中增加新的sql时需要获得该latch。
简化的sql执行过程:
(1)获得library cache latch根据hash value在library cache中查找是否存在可共享代码。存在则软解析,转向第(4)步。不存在则硬解析。
(2)释放library cache latch。获得shared pool latch,查找并锁定自由空间。
(3)释放shared pool latch,重新获得library cache latch,将sql及执行计划插入library cache中。
(4)释放library cache latch,保持null模式的library cache pin/lock。
(5)开始执行sql。
version_count过高通常会导致library cache latch长时间持有,从而影响性能。
v$session_longops 视图
v$sql v$sqlarea
从10g开始,v$sqlarea不再是v$sql的聚合,而是去掉了v$sql中为执行过的子指针之后再聚合。