还是继续整理eygle深入浅出中关于shared pool部分。
Shared pool共享池,初步仅仅只是理解为sql和pl/sql 数据字典的共享区,提供代码共享,当然这也是shared pool最重要的地方。在oracle
Alter system set events ‘immediate trace name heapdump leval
EXTENT 8 addr=28000000
Chunk 28000038 sz= 24 R-freeable "reserved stoppe"
Chunk 28000050 sz= 212888 R-free " "
Chunk 28033fe8 sz= 24 R-freeable "reserved stoppe"
Chunk 28034000 sz= 3491192 perm "perm " alo=3491192
Chunk 28388578 sz= 474392 perm "perm " alo=474392
Chunk 283fc290 sz= 14352 perm "perm " alo=14352
Chunk 283ffaa0 sz= 1376 free " "
EXTENT 9 addr=28800000
Chunk 28800038 sz= 24 R-freeable "reserved stoppe"
Chunk 28800050 sz= 212888 R-free " "
Chunk 28833fe8 sz= 24 R-freeable "reserved stoppe"
Chunk 28834000 sz= 3917776 perm "perm " alo=3917776
Chunk 28bf07d0 sz= 56176 perm "perm " alo=56176
Chunk 28bfe340 sz= 6160 perm "perm " alo=6160
Chunk 28bffb50 sz= 1200 free " "
Total heap size = 41942480
FREE LISTS:
Bucket 0 size=16
Bucket 1 size=20
Bucket 2 size=24
Bucket 3 size=28
Bucket 4 size=32
Bucket 5 size=36
Bucket 6 size=40
Bucket 7 size=44
Bucket 8 size=48
Bucket 9 size=52
……截取部分内容,其中oracle是
Shared pool通过free list管理free内存块(chunk),free的内存块(chunk)按不同的size被划分到不同部分bucket进行管理,感觉有点像buffer cache的bucket了!
数据库启动时,shared pool是连续内存块,但是当空间分配使用后,内存块开始被分割,碎片出现,bucket列表变长。
oracle请求shared pool空间时,首先进入相应bucket进行查找,找不到,则转向下一个非空的bucket,获取chunk后,分割这个chunk,剩余部分会进入相应bucket进一步增加碎片,最终是由于不停分割chunk,导致每个bucket的内存块越来越多,越来越小,而bucket 0最为严重(一般都是bucket 0的内存请求),碎片过多其实也就是相应的bucket上管理的细小的内存块过多,导致shared pool性能产生的根本原因。
细小内存块过多,导致oracle收索shared pool空闲内存块时间过长,收索free list时间过长,根据cache buffer的内容cache buffer lru是管理cache buffer中的lru链表收索空闲内存和管理lru链表,就需要获得该链表的latch,同样shared pool的free list链表也需要获得该链表的latch,也就是shared pool latch,而latch是oracle数据库内部低级锁,串行机制保证内存结构不被并发更新修改所损坏,虽然latch获取和释放都非常短(微秒级),但是繁忙的生产库latch的串行机制往往成为数据库的极大性能瓶颈。
Oracle 9I中,为了增加大共享池支持,shared pool latch从原来的一个增加到现在的7个。这一点可以查询视图v$latch_children验证。在oracle 9I后,由于shared pool的相应bucket算法改变,shared pool latch数量的增加,大共享池已经可以很大程序的提高数据库的性能,而不用过多的担心而带来的管理的消耗。
SQL> col name format a15;
SQL> select addr,name,gets,misses,spin_gets from v$latch_children where name='shared pool';
ADDR NAME GETS MISSES SPIN_GETS
-------- --------------- ---------- ---------- ----------
056BCECC shared pool 518465 145 143
056BCF34 shared pool 9 0 0
056BCF
056BD004 shared pool 9 0 0
056BD
056BD0D4 shared pool 9 0 0
056BD
7 rows selected
深入浅出中还提到,如果os有4个或4个以上cpu,并且shared pool大于250MB,oracle会把shared pool分割为多个子缓冲池进行管理,每个子缓冲池都拥有独立结构,LRU和shared pool latch。(不过自己暂时还没有办法验证该结论)子缓冲的数量由隐含参数_kghdsidx_count控制,该参数_kghdsidx_count默认值为1.
Shared pool的空闲分配和使用情况还可以用视图x$ksmsp,也就是Kernal Storage Memory Management Sga Heap,其中每一行代表着shared pool中的一个chunk。
Ksmchcom:注释字段,相应的有free memory,sql area,PL/SQL DIANA
Ksmchsiz:内存块大小
Ksmchcls:代表类型, recr包含可以被临时移出内存对象,在需要时可以这个对象可以被重建 free 不包含任何对象的chunk,freeabl 这部分内存可以被部分释放或全部释放,某些中间过程产生的对象不能被临时移出内存 ,perm 永久对象,不能被释放
SQL> select count(*) from x$ksmsp;
COUNT(*)
----------
29932
SQL> select count(*) from dba_objects where rownum<10;
COUNT(*)
----------
9
SQL> select count(*) from x$ksmsp;
COUNT(*)
----------
29939
可以看出由于shared pool中进行了sql解析,请求相应的free list上的bucket空间,分割chunk,导致产生了更细碎的内存chunk,如果数据库中存在大量的硬解析,会大量请求shared pool的free list的free空间,同样在收索free list中会占用shared pool latch,可能会产生shared pool latch竞争,也会产生更细更小的内存碎片,chunk也会增加,导致以后再次请求free内存时搜索free list的变长,又会产生shared pool latch竞争,影响数据库性能。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/25362835/viewspace-1056852/ ,如需转载,请注明出处,否则将追究法律责任。