loading...

Shared Pool体系结构进化论

分享
标签: shared  pool  latch  _kghdsidx_count  分类: Oracle 2008-01-06 21:38

       在ORACLE 7之前,连接oracle的每一个会话都有一个服务器进程为它服务,这个服务器进程的作用是解析(parse),优化(opimize)客户端提交的PL/SQL或SQL代码.就算客户端向各个服务器进程提交的PL/SQL,SQL代码一样,各个服务器进程并不会share cursor,刚开始采用这种设计方式也并没有什么性能问题。但随着客户端数量的高速增长,以及在OLTP SQL语句执行频率高速增长的情况下,ORACLE 7版本的数据库的这种设计就开始出现了性能问题。当执行一样的SQL或PL/SQL代码时,如果执行计划或其它一些信息可以被所有的服务器进程所共享,而不用重新去产生,那么将可以节约大量的时间。当时oracle已开始意识到此问题,并开始着手进行改进,采用了如下的方法:
1.扩展SGA variable portion
2.提供一种方法来管理和访问SGA variable portion中的shared objects
3.ORACLE内存管理的增强

      在ORACLE7,8,8i 时,开始明确提出了共享池(shared pool)的概念,此时的共享池Shared Pool也有了更多的内容:包含共享SQL区和数据字典存储区。在shared pool设计方面,采用了如下的体系结构:

从上图可以看出,整个共享池只有一个池,bucket的个数也非常的少,据说只有11个.采用这种设计方式,从性能上来讲,已经比oracle早期的版本在性能上有了比较大的飞越,毕竟各个服务器进程已经可以用共享SQL语句的执行计划等信息,而产生执行计划的数据字典信息也在共享池shared pool被缓存住了。这一切看似perfect了,但很快又遇到了新的问题:
1.由于共享池只有一个子池,那么对shared pool latch的争用相当的激烈
2.由于只有一个子池,再加上桶的个数少,那么单个bucket上的列表将会非常的长,搜索花的时间也比较多,进一步加剧了shared pool latch的争用
3.共享池内存碎片管理问题

        在ORACLE 9i时,共享池有了进一步的改进,
1.共享池最多可以有七个子池,每个子池最小为128M;
2.增加了bucket桶的个数;
3.改进了共享池的内存空间管理方式

结构可以用如下图表示:

library cache采用如下的搜索结构:

我们要搜索一个SQL或者PL/SQL对象是否在shared pool中,首先要获得library cache latch,如果找到,则在library cache handle上加NULL模式的锁,其次把library cahce object pin住,找到执行计划后,开始执行;如果所要搜索的对象不在library cahce中或者进行DDL操作时,librarary cahce中已存在的相关的SQL,PL/SQL失效,那么将会发生library cache load lock等待,此时即会发生在sub shared pool中搜索连续的空闲空间来储存硬解析产生新的执行计划,如果这个时候,没有连续的空闲空间,或者查找连续空闲空间的速度过慢,那么在一个高并发的OLTP的系统中,将会爆发大量的library cahce pin等待。由于共享子池的增多,再加上bucket数量的增加,使得单条双向链表较短,查找连续的空间会比较快,大大减少了shared pool latch的争用。正是由于ORACLE 9i在共享池处理技术上的巨大突破,使得oracle数据库的性能有了大幅度的提升,为oracle称霸全球数据库市场打下了坚实的基础。直到今天,全球大型的OLTP应用大部份都是建立在ORACLE 9I数据库之上的。

oracle 9i关于共享子池个数以及大小的控制(from Doc ID:  Note:396940.1):

The number of subpools is calculated using a simple algorithm. 
1. a subpool must be at least 128MB in 9i releases. 
2. there can be one subpool for every four CPUs on the system, up to 7 subpools.
The number of subpools can be explicitly controlled using the init.ora parameter _kghdsidx_count.
There is no parameter to explicitly control the size of each subpool.


不管是oracle 8i,还是oracle 9i经常会碰到ORA-4031错误,关于4031经典错误,手册里是如下的描述:

ORA-04031 unable to allocate string bytes of shared memory ("string","string","string","string")
Cause: More shared memory is needed than was allocated in the shared pool.
Action: If the shared pool is out of memory, either use the DBMS_SHARED_ POOL package to pin large packages, reduce your use of shared memory, or increase the amount of available shared memory by increasing the value of the initialization parameters SHARED_POOL_RESERVED_SIZE and SHARED_ POOL_SIZE. If the large pool is out of memory, increase the initialization parameter LARGE_POOL_SIZE.

导致此错误的原因是某个共享子池满了,无法在此共享子池中再分配一定大小的连续内存空间,经常采用的办法是增大共享池来解决这一类的问题。

       在oracle 10g,整个共享池的体系结构并没有什么变化,只是单个共享子池大小从9i的128M变成至少为256M,我们不禁要问,oracle为什么要去修改此设置,增大了共享子池的最小值?我猜想,大概是基于如下的考虑:
1.128M的共享子池,容易发生空间满的情况,导致ORA-4031错误发生
2.256M的共享子池,单个共享子池的管理负担并不会加重,性能也没什么大的影响

       从oracle shared pool在各个版本的数据库体系结构的不断变化,其设计思想的不断改进,我们是否能从中得到一些启发呢?偶就在这里先抛砖呢?在存放大数据量的表上采用分区表的组织形式,在分区表上创建并且使用local index来检索数据,与shared pool的结构上似乎有许多相似之处,至于其它的地方,期待您的见解

分享 分享 |  评论 (0) |  阅读 (?)  |  固定链接 |  类别 (Oracle) |  发表于 21:38  | 最后修改于 2008-02-14 09:18
 
表  情:
加载中...