Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2898097
  • 博文数量: 599
  • 博客积分: 16398
  • 博客等级: 上将
  • 技术积分: 6875
  • 用 户 组: 普通用户
  • 注册时间: 2009-11-30 12:04
个人简介

WINDOWS下的程序员出身,偶尔也写一些linux平台下小程序, 后转行数据库行业,专注于ORACLE和DB2的运维和优化。 同时也是ios移动开发者。欢迎志同道合的朋友一起研究技术。 数据库技术交流群:58308065,23618606

文章分类

全部博文(599)

文章存档

2014年(12)

2013年(56)

2012年(199)

2011年(105)

2010年(128)

2009年(99)

分类: Oracle

2011-11-14 17:15:47

 转自:
 
 1.3 理解共享池  
 

共享池是Oracle 数据库中的一个十分重要的缓冲池。实际上我们在SQL*PLUS中使用show sga命令就可以看到SGA的几个主要组成部分:

SQL> show sga

Total System Global Area 1048576000 bytes

Fixed Size                  1271444 bytes

Variable Size             511707500 bytes

Database Buffers          532676608 bytes

Redo Buffers                2920448 bytes

SQL> 

Oracle SGA包含固定数据结构部分(FIXED SIZE),数据块缓冲区(Database  Buffers )、Redo Log 缓冲区(Redo  Buffers )和共享池(包含在Variale Size 中)等几大部分。固定数据结构部分包含了数据库的一些固定的数据结构,包括所有其他共享内存结构的地址和指针等。

共享池是SGA中的一个组件,传统的概念上我们认为共享池包含字典缓冲(row cache)和库缓冲(library cache)两个部分。实际上共享池的结构要复杂的多,共享池中还包含数据库的一些十分重要的数据结构,比如资源、锁等。通过下面的SQL我们可以了解到共享池中包含的组件:

SELECT pool, name, bytes FROM v$sgastat where pool='shared pool';

共享池中有很多组件,而且共享池也是很多会话为自己执行SQL分配共享内存的缓冲池,这些在共享池中分配的内存是会话之间使用十分频繁的,也是希望能够一次分配多次使用的。和DB CACHE不同,DB CACHE可以根据BLOCK SIZE很规则的进行均匀分配,会话在共享池中分配空间的时候,所需要的空间差异很大,有的只有几十个字节,而有的需要几百K甚至几M。为了确保访问的性能,共享池的每次内存分配都必须分配连续的内存空间。因此经过一段时间的运行,共享池中或多或少都会出现一些碎片。这些碎片分布在一些连续分配的空间之间。

共享池中分配的内存空间,有些是永久使用,不会释放的,这些内存空间被标识为permanent,这些结构大多数是在实例启动的时候就分配的,也有一些是在系统运行过程中临时分配的,不过这些内存的特点是只分配,在实例关闭前基本上不会释放。最为典型的永久性内存包括进程信息数据、会话信息数据和一些特殊用途的内存段。进程信息和会话信息所使用的内存是根据参数processessessions参数在实例启动时一次性分配的,一旦分配就不会变动,也不会动态扩展。因此如果我们想要加大processes参数,必须重启实例才能够起作用。另外一些特殊用途的内存数组也是根据参数在实例启动时进行分配,但是在数据库实例运行过程中,如果这些数组出现不足,是可以动态扩展的。这些动态扩展的内存也是permanent的,一旦分配就不会释放。这些数组包括enqueues(lock)enqueue resourcetransactionstransaction branches等,对于RAC系统,还有gcs resourceges resource等。

还有一些分配的内存是可释放的,被标志为freeable或者recreateableFreeable的内存是可以直接释放的,而recreateable的内存只需要unpin后也是可以释放的。因此这两部分内存都是可以重用的内存。

共享池的内存是通过Oracle 通用内存管理(generic Oracle memory manager)来进行管理的,这个管理机制也就是我们常说的KGH heap Manager。在KGH heap Manager机制下,所有的共享池的free内存都被挂在被称为freelists的空闲链表上。这个空闲列表是按照buckets的机制建立的。根据空闲内存片段的大小,挂在不同的bucket上。以Oracle  9i为例,共享池的freelists包含256buckets,每个buckets上链接了不同大小的空闲内存块。具体情况如下:

小于812字节的BUCKET是以4字节为增长步长的:16字节、20字节、24字节,...812字节

超过812字节的BUCKET是以64字节为增长步长的:876字节、940字节,...4012字节

超过4012字节的BUCKET增长是以4096的倍数倍增方式增长的:4108, 8204, 16396, 32780, 65548...

当某个会话需要从共享池中分配空间的时候,会根据自己分配的大小找到某个BUCKET,然后找到一个空闲的内存,从中分配。分配产生的剩余内存,会被挂到相应的BUCKET上,供其他会话分配使用。而被释放的内存又会被挂到FREELISTS上,为了确保共享池的内存运行一段时间后不会碎片化,被释放的内存会自动进行合并,如果释放的两个内存片段是相邻的,Oracle 会自动合并为一个大内存。

共享池的大小通过参数shared_pool_size来定义。在Oracle 共享内存自动管理或者Oracle 自动内存管理模式下,可以不设置shared_pool_size参数,由数据库自动来根据系统负载分配共享池内存。如果这种情况下,我们设置了shared_pool_size参数,那么这个参数会作为共享池的初始大小和最小大小。无论内存如何自动调整,共享池的大小不能小于这个值。

阅读(2018) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~