[AD]共享池历程概述

一,Shared Pool 的基本原理
1,SharedPool是Oracle SGA设置中最复杂也是最重要的一部分内容,Oracle通过Shared Pool来实现SQL共享、减少代码硬解析,从而提高数据库的性能。在某些版本中,如果设置不当,SharedPool可能会极大地影响数据库的正常运行。
2,在Oracle 7i之前,Shared Pool并不存在,每个Oracle连接都有一个独立的Server进程与之相关联,Server进程负责解析、优化所有SQL和PL/SQL代码。典型地,在OLTP环境中,很多代码具有相同或类似的结构,反复的独立解析浪费了大量的时间和资源,Oracle最终认识到这个问题,并且从PL/SQL开始尝试把这部分可共享的内容进行独立存储和管理,于是SharedPool作为一个独立的SGA组件开始被引入,并且其功能和作用被逐渐的完善和发展起来。
3,在这里注意到:SharedPool最初被引入的目的,也就是它的本质功能是实现共享。如果你的系统代码完全异构(假如你的代码从不绑定变量,从不反复执行),那么你会发现,这个时候SharedPool完全成为了一个负担,它在徒劳无功地进行无谓的努力:保存代码、执行计划等期待重用,并且客户端要不停地获取Latch,试图寻找共享代码,却始终一无所获。如果真是如此,那这是我们最不愿看到的情况,SharedPool变得有害无益。当然这是极端,可是我们在性能优化中我们发现,大多数性能低下的系统都存在这样的通病:代码极少共享,缺乏或从不实行变量绑定。优化这些系统的根本方法就是优化代码,使代码(在保证 性能的前提下)可以充分共享,减少无谓的反复硬/软解析。
4,实际上,Oracle引入Shared Pool就是为了帮助用户实现代码共享和重用。了解这一点之后,开发人员在应用开发过程中,也应该有意识提高自己的代码水平,以期减少数据库的压力。
二,Shared Pool的设置说明
1,Shared Pool的大小通过初始化参数shared_pool_size 设置。对于SharedPool的设置,一直以来是最有争议的一部分内容。一方面很多人建议可以把SharedPool设置稍大,以充分Cache代码和避免ORA-04031错误的出现;另一方面又有很多人建议不能把Shared Pool设置过大,因为过大可能会带来管理上的额外负担,从而会影响数据库的性能。
2,可以通过如下命令转储Shared Pool共享内存的内容。
SQL> alter session set events 'immediate trace name heapdump level 2';
Session altered.
SQL> @gettrcname
TRACE_FILE_NAME
--------------------------------------------------
/u01/app/oracle/admin/orcl/udump/orcl_ora_3152.trc
Shared Pool通过Free Lists管理Free内存块(chunk),free的内存块(chunk)按不同size被划分到不同的部分(Bucket)进行管理。结合Dump文件,可以通过图对SharedPool的Free List管理进行说明。



3,在oralce 10g中,不同Bucket管理的内存块的size范围如下
[oracle@rhel ~]$ cat /u01/app/oracle/admin/orcl/udump/orcl_ora_3152.trc | grep Bucket
 Bucket 0 size=16
 Bucket 1 size=20
 Bucket 2 size=24
 Bucket 3 size=28
         .
         .
         .
 Bucket 172 size=704
 Bucket 173 size=708
 Bucket 174 size=712
 Bucket 175 size=716
 Bucket 176 size=724
 Bucket 177 size=732
 Bucket 178 size=740
 Bucket 179 size=748
4,在这里小于16bytes的块位于Bucket 0上,如果大于16bytes小于20bytes在Bucket1上。
20-16=4
24-20=4
724-716=8
748-740=8
可以看到以4bytes递增,8bytes递增......
5,初始时,数据库启动以后,SharedPool多数是连续的内存块。但是当空间分配使用后,内存块开始被分割,碎片开始出现,Bucket列表开始变长。Oracle请求SharedPool空间时,首先进入相应的Bucket进行查找。如果找不到,则转向下一个非空的Bucket,获取第一个Chunk,分割这个Chunk,剩余部分会进入相应的Bucket,进一步增加碎片。
6,最终结果是,由于不停分割,每个Bucket上的内存块会越来越多,越来越小。通常Bucket 0 的问题会最为显著,在这个测试的小型数据库上,Bucket 0上的碎片已经达到9030个,而shared_pool_size设置仅为150MB。
7,通常如果每个Bucket上的Chunk多于2000个,就被认为是SharedPool碎片过多。而SharedPool的碎片过多,是SharedPool产生性能问题的主要原因。
8,碎片过多会导致搜索Free List的时间过长,而Free Lists的管理和搜索都需要获得和持有一个非常重要的Latch,就是Shared Pool Latch 。Latch是Oracle数据库内部提供的一种低级锁,通常串行机制保护共享内存不被并发更新/修改所损坏。Latch的持有通常都非常短暂(通常微秒级),但是对于一个繁忙的数据库,这个串行机制往往会成为极大的性能瓶颈。
9,如果Free List链表过长,搜索这个Free Lists的时间会变长,从而可能导致Shared Pool Latch被长时间持有,在一个繁忙的系统中,这会引起严重的Shared Pool Latch竞争。在Oracle 9i之前,这个重要的Shared Pool Latch只有一个,所以长时间持有将会导致严重的性能问题。而在大多数情况下,用户请求的都是相对小的内存块(chunk),这样搜索Bucket 0往往消耗了大量的时间以及资源,Latch的争用此时就会成为一个非常严重的问题。
10,对比Oracle 8i,在Oracle 9i中shared pool管理最为显著的变化是,对于数量众多的Chunk,Oracle增加了更多的Bucket来管理(这与之前讲过的Buffer Cache的增强非常相似)。0~199共200个Bucket,size以4为步递增,200~249共50个Bucket,size以64递增,这样每个Bucket中容纳的chunk数量大大减少,查找的效率得以提高。所以,在Oracle 9i之前,如果盲目地增大shared_pool_size 或者设置过大的shared_pool_size,往往会适得其反。这就是也许你曾经听
说过的“过大的Shared_pool会带来管理上的负担”。
11,而且在Oracle 9i中,为了增加对于大共享池的支持,Shared Pool Latch从原来的一个增加到现在的7个,如果用户的系统有4个或4个以上的CPU,并且shared_pool_size大于250MB,那么Oracle可以把sharedPool分割为多个子缓冲池进行管理,每个subpool都拥有独立的结构、LRU和Shared Pool Latch。
四,子缓冲池
1,SQL> select addr,name,gets,misses,spin_gets from v$latch_children where name='shared pool';
ADDR     NAME                                                     GETS     MISSES  SPIN_GETS
-------- -------------------------------------------------- ---------- ---------- ----------
20095BF4 shared pool                                            336139          5          0
20095C58 shared pool                                                10          0          0
20095CBC shared pool                                                10          0          0
20095D20 shared pool                                                10          0          0
20095D84 shared pool                                                10          0          0
20095DE8 shared pool                                                10          0          0
20095E4C shared pool                                                10          0          0
7 rows selected.
2,子缓冲的数量有一个新引入的隐含参数设置_KGHDSIDX_COUNT。可以手工调整该参数(仅限于实验环境研究用)。以观察共享池管理的变化。
SQL> alter system set "_kghdsidx_count" =2 scope=spfile;
System altered.
3,SQL> startup force;
ORACLE instance started.
Total System Global Area  314572800 bytes
Fixed Size                  1219184 bytes
Variable Size             109053328 bytes
Database Buffers          201326592 bytes
Redo Buffers                2973696 bytes
Database mounted.
Database opened.
SQL>
4,SQL> select addr,name,gets,misses,spin_gets from v$latch_children where name='shared pool';
ADDR     NAME                                                     GETS     MISSES  SPIN_GETS
-------- -------------------------------------------------- ---------- ---------- ----------
20095BF4 shared pool                                             38914          0          0
20095C58 shared pool                                              3618          0          0
20095CBC shared pool                                                 6          0          0
20095D20 shared pool                                                 6          0          0
20095D84 shared pool                                                 6          0          0
20095DE8 shared pool                                                 6          0          0
20095E4C shared pool                                                 6          0          0
7 rows selected.
五,了解X$KSMSP视图
1,Shared Pool的空间分配和使用情况,可以通过一个内部视图来观察,这个视图就是X$KSMSP。X$KSMSP的名称的含义为[K]ernal [S]torge [M]emory [M]anagement [S]GA Hea[P]其中的每一行都代表着SharedPool中的一个chunk。
2,SQL> desc x$ksmsp
 Name                                                                                                              Null?    Type
 ----------------------------------------------------------------------------------------------------------------- --------

----------------------------------------------------------------------------
 ADDR                                                                                                                       RAW(4)
 INDX                                                                                                                       NUMBER
 INST_ID                                                                                                                    NUMBER
 KSMCHIDX                                                                                                                   NUMBER
 KSMCHDUR                                                                                                                   NUMBER
 KSMCHCOM                                                                                                                   VARCHAR2(16)
 KSMCHPTR                                                                                                                   RAW(4)
 KSMCHSIZ                                                                                                                   NUMBER
 KSMCHCLS                                                                                                                   VARCHAR2(8)
 KSMCHTYP                                                                                                                   NUMBER
 KSMCHPAR                                                                                                                   RAW(4)
SQL>
3,这里主要关注的几个字段
a,x$ksmsp.ksmchcom,是注释字段,每个内存块被分配以后,注释会添加在该字段中。
b,x$ksmsp.ksmchsiz,代表块大小。
c,x$ksmsp.ksmchcls,列代表类型,主要有4中类,说明如下
c1,Free ---Free Chunks:不包含任何对象的chunk,可以不受限制的被自由分配。
c2,recreat---Recreate Chunks:包含可以被临时移出内存的对象,在需要的时候,这个对象可以被重新创建。例如:许多存储共享SQL代码的内存都是可以重建的。
c3,Freeable---Freeable Chunks:包含session周期或调用的对象,随后可以释放。这部分内存有时候可以全部或部分提前释放,但是注意,由于某些对象是中间过程产生的,这些对象不能临时释放出内存(因为不可重建)。
c4,Perm ---Permanent Memory Chunks:包含永久对象,通常不能释放。
4,可以通过查询X$KSMSP视图来考察SharedPool中存在的内存片的数量。不过要注意,Oracle(如:10.1.0.2)版本
在某些平台上(如:HP-UX PA-RISC 64-bit)查询该视图时可能会导致过度的CPU耗用,这是由Bug引起的。
5,SQL> select count(*) from x$ksmsp;
  COUNT(*)
----------
     15690
SQL> select count(*) from dba_objects;
  COUNT(*)
----------
     50396
SQL> select count(*) from x$ksmsp;
  COUNT(*)
----------
     15709
SQL>
6,这是由于SharedPool中进行SQL解析,请求空间,进而导致请求free空间分配、分割、从而产生了更多、更碎的内存Chunk。由此可以看出,如果数据库系统中存在大量的硬解析,不停请求分配Free的SharedPool内存,除了必须的Shared Pool Latch竞争外,还不可避免会导SharedPool中产生更多的内存碎片(当然在内存回收时,可能看到Chunk数量减少的情况)。
六,实验一(查询前后SharedPool的变化)
1,创建一张临时表用以保存之前X$KSMSP的状态:
SQL> CREATE GLOBAL TEMPORARY TABLE e$ksmsp on COMMIT PRESERVE ROWS AS
  2  SELECT a.ksmchcom,
  3  SUM(a.CHUNK) CHUNK,
  4  SUM(a.recr) recr,
  5  SUM(a.freeabl) freeabl,
  6  SUM(a.SUM) SUM
  7  FROM (SELECT ksmchcom,COUNT(ksmchcom) CHUNK,
  8  DECODE (ksmchcls,'recr',SUM(ksmchsiz),NULL) recr,
  9  DECODE (ksmchcls,'freeabl',SUM(ksmchsiz),NULL) freeabl,
 10  SUM(ksmchsiz) SUM
 11  FROM x$ksmsp GROUP BY ksmchcom,ksmchcls) a
 12  where 1=0
 13  GROUP BY a.ksmchcom;
Table created.
2,插入数据
SQL> INSERT INTO E$KSMSP
  2  SELECT a.ksmchcom,
  3  SUM(a.CHUNK) CHUNK,
  4  SUM(a.recr) recr,
  5  SUM(a.freeabl) freeabl,
  6  SUM(a.SUM) SUM
  7  FROM (SELECT ksmchcom,COUNT(ksmchcom) CHUNK,
  8  DECODE(ksmchcls,'recr',SUM(ksmchsiz),NULL) recr,
  9  DECODE(ksmchcls,'freeabl',SUM(ksmchsiz),NULL) freeabl,
 10  SUM(ksmchsiz) SUM
 11  FROM x$ksmsp
 12  GROUP BY ksmchcom,ksmchcls) a
 13  GROUP BY a.ksmchcom;
82 rows created.
3,比较前后SharedPool内存分配的变化;
SQL> select a.ksmchcom,a.chunk,a.sum,b.chunk,b.sum,(a.chunk-b.chunk) c_diff,(a.sum-b.sum) s_diff
  2  from
  3  (SELECT a.ksmchcom,
  4  SUM(a.CHUNK) CHUNK,
  5  SUM(a.recr) recr,
  6  SUM(a.freeabl) freeabl,
  7  SUM(a.SUM) SUM
  8  FROM (SELECT ksmchcom,COUNT(ksmchcom) CHUNK,
  9  DECODE(ksmchcls,'recr',SUM(ksmchsiz),NULL) recr,
 10  DECODE(ksmchcls,'freeabl',SUM(ksmchsiz),NULL) freeabl,
 11  SUM(ksmchsiz) SUM
 12  FROM x$ksmsp
 13  GROUP BY ksmchcom,ksmchcls) a
 14  GROUP BY a.ksmchcom) a,e$ksmsp b
 15  where a.ksmchcom = b.ksmchcom and (a.chunk-b.chunk)<>0;
KSMCHCOM              CHUNK        SUM      CHUNK        SUM     C_DIFF     S_DIFF
---------------- ---------- ---------- ---------- ---------- ---------- ----------
obj htab chun            20     143680         19     136496          1       7184
free memory             223   12545964        196   13194916         27    -648952
Heap0: KGL              595     638828        498     534844         97     103984
KGL handles            3127    1530848       2616    1278288        511     252560
modification             13      26780         12      24720          1       2060
trigger defini           10       4988          7       2784          3       2204
type object de          176     185172        179     190888         -3      -5716
KGLS heap               775    1023852        995    1260848       -220    -236996
obj stat memo           290      88160        256      77824         34      10336
KQR SO                  332     208976        248     156192         84      52784
repository               45      40964         30      28112         15      12852

KSMCHCOM              CHUNK        SUM      CHUNK        SUM     C_DIFF     S_DIFF
---------------- ---------- ---------- ---------- ---------- ---------- ----------
table definiti            9       1924          2        168          7       1756
sql area:PLSQL           41     169704         44     182128         -3     -12424
PCursor                 707     758056        618     662648         89      95408
CCursor                1070    1161156       1055    1145076         15      16080
library cache          1075     103264       1053     101128         22       2136
sql area                862    3531860        888    3638236        -26    -106376
PL/SQL DIANA            295    1208320        282    1155072         13      53248
KQR PO                 2062    1035688       1775     890436        287     145252
PL/SQL MPCODE           455    1945408        398    1713508         57     231900
CURSOR STATS             40     165760         35     145040          5      20720
21 rows selected.
SQL>
4,分析
free memory             223   12545964        196   13194916         27    -648952
简单分析结果,首先free memory的大小减少了648952,这说明SQL解析存储占用了一定的内存空间,而chunk数从196增加到223,说明内存碎片增加了,而碎片增加是共享池性能下降的开始。

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/29611940/viewspace-1147475/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/29611940/viewspace-1147475/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值