内存结构

oracle主要有3种内存结构:

1>SGA:系统全局盘区(system global area)---这是一个大的、共享的内存段,本质上,所有的oracle进程都将在一点或另一点上访问它。

2>PGA:进程全局盘区(process global area)---这是内存,对单一的进程或线程是私有的,从其他的进程或线程上无法访问它。

3>UGA:用户全局盘区(USER Blobal area)--这是与会话有关的内存部分。可以SGA或PGA上找到它,这取决于是在MTS模式(那么就在SGA中)还是在慎用服务器上运行(那么就在PGA中)。

1.PGA和UGA

        PGA是内存的进程段,这是一个单一的操作系统进程或线程的特定内存。这个内存不可以被系统中其他的进程或线程所访问。PGA不会在oracle的SGA之外分配---它总是由进程或线程在本地进行分配。

       UGA实际上是会话的状态。它是会话必须始终能够得到的内存。UGA的位置总体上依赖于oracle为了接受连接而实施的配置。如果已经配置了MTS,那么UGA必须在每个从都获得访问的内存结构中---这应该是SGA。用个方法,会话可以使用任何一个共享服务器,因为它们中的任何一个都可以读取或写入会话数据。另一方面,如果正在使用专用服务器连接,对会话状态的统一访问的需求就会消失,UGA本质上变得与PGA同义--实际上包含在PGA中。

       对PGA/UGA的大小影响最大的因素是init.ora或会话级参数SORT_AREA_SIZE和SORT_AREA_RETAINED_SIZE。这两个参数控制在写盘之前oracle用来进行数据排序的空间数量,以及在排序完成之后将保留多少内存段。SORT_AREA_SIZE通常分开在PGA 之中,而SORT_AREA_RETAINED_SIZE则在PGA之内。通过查询一个特殊 的oraclev V$表来监控UGA/PGA的大小,该表也称为动态性能表。使用这些V$表,可以发现当前PGA和UGA内存的使用状态。

       uga的信息在 系统表v$statname及V$mystat中,可以有通过下面语句查看uga部分信息,

sql>select a.name,b.value from v$statname a,v$mystat b  where a.statistic#=b.statistic# and a.name like '%ga%'

可以得到如下数据:

NAME                                               VALUE

---------------------------------------------------------------

session uga memory                        1216836

session uga memory max                1274824

session pga memory                        1760852

session pga memory max                1826388

calls to kcmgas                                            0

所以在开始之前,可以看到在UGA中大约有120KB数据,而在PGA中大约有170KB数据。第一个问题是,在PGA和UGA之间使用多少内存。这是一个带欺骗性的问题,也是一个无法回答的问题,除非知道是通过 专用 服务器还是通过MTS上的共享服务器进行连接的。即使如此,也是很难估计出来的。在专用服务器模式下,UGA全部包含于PGA之中。这时,可能在进程或线程中消耗170KB内存。在MTS模式下,UGA是从SGA中分配 的,PGA在的服务器中。所以,在MTS模式下,当从上面查询中获得最后一千时,进程可能正在被另一个人使用。PGA不是“您的”,所以,从技术角度讲正在使用120KB内存(当正在实际地运行查询时除外,这时正在使用混合在PGA和UGA之间的290KB内存)。

现在,考察对PGA/UGA有何影响:

sql>show parameter sort_area;

NAME                                           TYPE                    VALUE

--------------------------------------    -------------------           ------------------

sort_area_retained_size            integer                      0

sort_area_size                           integer                      65536

sql>select * from all_objects order by 1,2,3,4;

............(control+c after several pages of data).............

得到的结果:

NAME                                                   VALUE

----------------------------------------             -----------------

session uga memory                            2390396

session uga memory max                    8143752

session pga memory                            3071572

session pga memory                            8511060

calls to kcmgas                                                 0

如上所示,这次PGA有了显著的增长。 

2.SGA每一个oracle的实例都有一个大内存结构,它们共同被看作是SGA系统全局盘区。这是一个大型的、共享的内存结构,每个oracle进程将在此时或彼时访问它。它的容量变化范围很大,从小型测试系统上的几个MB到大中型系统的百MB,以及真正大型系统上数个GB。

      在UNIX操作系统中SGA是一个物理实体,可以从操作系统命令行上“看到”它。它物理地实现为信斯言也内存段(进程可能附属的独立内存片)。在没有任何oracle进程的系统上可能有一个SGA,内存是独立的。然而应该注意,如果有一个没有oracle进程SGA,它表明数据库已经以某种方式破坏。这虽然是不正常的情况,但它会发生。

      在windows中,您不能像在UNIX中那样看到SGA。因为oracle作为单独进程,在那个平台上以单独的地址空间执行,所以SGA和为私有的内存分配经oracle.exe进程。

      不管是什么平台,在oracle本身之中,可以看到SGA。有另外一个神奇的V$表称为V$SGASTAT。它看起来如下 所示:

sql>compute sum of bytes on pool;

sql>break on pool skip1;

sql>select pool,name,bytes

  2 from v$sgastat

  3 order by pool,name;

POOL                  NAME                                          BYTES

--------------           ---------------------                            ----------------------

java pool             free  memory                                18366464

.................

SGA 人为各种池(pool):

  1>Java池(Java pool)-----Java池是分配给在数据库上运行的JVM的固定大小的内存。

  2>大池(Large pool)-----大池被MTS用途运放内存;被Parallel Execution(并行计算)用作消息缓冲器;并被RMAN Backup用作I/O缓冲器。

  3>共享池(Shared pool)---共享池包含共享的游标、存储过程、声明对象、字典高速缓存和许多成打的其他数据位。

  4>空池(The "NULL" pool)---这个池不真正拥有名字。这是专门用于块缓冲区(高速缓存的数据库块)、重做日志缓冲区以及“固定SGA”盘区的内存。

        init.ora中参数对SGA的大小最有影响:

1>JAVA_POOL_SIZE----控制java池的大小

2>SHARED_POOL_SIZE-----把共享池的大小控制在某种程序上

3>LARGE_POOL_SIZE----控制大池的大小

4>DB_BLOCK_BUFFERS----控制块的缓冲区高速缓存大小

5>LOG_BUFFER---把重做缓冲器的大小控制在某种程序上

    除了SHARED_POOL_SIZE和LOG_BUFFER这两个例外,在init.ora参数和在SGA中分配的内存的数量有一对一的对应关系。例如,如果用数据库块大小乘上DB_BLOCK_BUFFERS,通常将从V$SGASTAT(为寄存器增加了一些开销)中的空池中获得DB_BLOCK_BUFFERS行的大小。如果研究大池的V$SGASTAT的字节问题,它将和LARGE_POOL_SIZE参数一样。

3.固定的SGA

      固定的SGA(Fixed SGA)是SGA的一个组件,其大小随平台和版本的变化而变化。在安装的时候,它被“编译”到oracle二制文件中(因此,命名为“固定”)。固定的SGA包含一组指向其他SGA组件的变更,以及包含着不同的参数值的参数值的变量。固定SGA的大小无法控制,它通常是非常小的。将这个盘区考虑成SGA的“自举”部分,oracle内部用来寻找SGA其他的位和片。

4.重做缓存

    重做缓存是需要写到联机重做日志中的数据在写到磁盘上之前临时高速缓存 的地方。由于对内存对内存的传输要远远快于内存对硬盘的传输,所以重做日志缓存可以加快数据库的操作速度。数据在重做缓存驻留的时间不会太长。实际上,这一盘区的内容会在下列情况刷新:

         每3秒钟,或有人提交时,或1/3满时,或包含了1MB的调整缓存 的重做日志数据时

         由于这些原因,有数十MB用于重做缓存通常是对内存的浪费。例如,为了使用6MB的重做调整缓冲区高速缓存,必须有很长的事务运行,以便每3秒钟或更短的时间内生成2MB的重做日志。如果系统中的某在3秒这一时间段中提交,将总也使用不了2MB重做日志空间。它被连续不断的刷新。从大于几兆字节 的重做缓存中获益的系统是非常少的。

 

    LOG_BUFFER init.ora参数控制重做缓存的默认大小,最大是512KB和(128*CPU个数)。这个盘区的最小大小是平台支持的最大数据库块的大小的4倍。如果您想要找出其大小,只要将LOG_BUFFER设置为1个字节,并重新启动数据库。在windows2003中可以看到如下结果:

sql>show parameter log_buffer

NAME                        TYPE                                VALUES

--------------------------   -----------------------------       -------------------

log_buffer                  integer                               28999456

sql>select * from v$sgastat  where name='log_buffer';

POOL                    NAME                              BUTYES

------------------         ---------------                      -----------------

                              log_buffer                        2945024

********************                                          --------------------

sum                                                               2945024

可以真正拥有最小的日志缓存,而不管init.ora设置,最小日志缓存将近30KB。实际上,还要稍大一点:

sql>select * from v$sga where name='Redo Buffers';

NAME                                        VALUES

----------------------                       ----------------------  

Redo Buffers                            2945024

5.块缓冲区高速缓存

      迄今为止,已经介绍了相对小的SGA组件。现在介绍巨大的组件。块缓冲区调整缓存是oracle在将数据库写入磁盘之前以及从磁盘上读取数据块之后,数据库块所存储的地方。这是SGA至关重要的盘区。将它设定得太小,那么查询就会永远地执行下去。设定得太大,则会影响其他进程(例如,将不会留给专用服务器足够空间来创建它的PGA,甚至无法启动)。

     缓冲区高速缓存中的块基本上在两个不同的列表中管理。块的“脏”表,需要用数据库块书写器(DBWn)来写入。随后,是一个“不脏”的块的列表。在过去的oracle8.0及以前版本中是最近最少使用法(LRU)列表。块以使用的顺序列出。在oracle8i及之后的版本中,算法有略微更改。不再使用过去的以某种物理顺序排列的块列表,oracle8i使用了一个块时,它列表,oracle使用了一个“接触计数(touch count)”计划。每次在缓存器中接触一个块时,它有效地增加与块相关的计数器。可以在一个真正神奇的表:X$表中看到。这些X$表在oracle中没有正式文档,但关于它们信息不时地泄露出来。

       X%BH表显示块缓冲区高速缓存中的有关块的信息。这里,可以看到随着接触块的次数增加,“接触计数”就增加。首先,需要发现一个块。将使用DUAL表中的一个表。DUAL表是一个特殊的表,它在所有的oracle数据库中只可以看到一个行和一个列。有必要知道该块的文件号和块号。

sql>select  file_id,block_id

     2 from dba_extents

     3 where segment_name='DUAL' and owner='SYS';

FILE_ID                                 BLOCK_ID

----------------------                    ----------------------

                       1                                    345

现在,可以使用那些信息来查看在块上的“接触计数”:

sql>select tch from x$bh where file#=1 and dbablk=345;

tch

-----

10

sql>select * form dual;

D

--

X

select tch from x$bh where file#=1 and dbablk=345;

TCH

------

11

每次接触那个块,计数就上升。缓存不再像过去那样移动到表的头部,它停留在它在表中的位置,且其“接触计数”增加了。块将自然地趋向于在表中不时地移动,因为块从列表取出,并放进了脏表(被DBWn写进磁盘)。同样,当它们重用时,当缓冲区高速缓存实际上充满时,一些带有小“接触计数”的块被从列表取出,它将以新的数据替换回列表中间合适的地方。用于管理这些列表的全部算法相当复杂,并随着oracle版本的升级,而地改变。作为开发人员,与实际的全部细节没有关系,但要注意,频繁使用的块将被高速缓冲存储,使用不频繁的块不会长时间地高速缓冲存储。

6.共享池(shared pool)

        shared pool是SGA中最关键的内存片段,特别是在性能和可伸缩性上。

        shared pool是oracle高速缓存许多位“程序”数据的地方。当分析 一具查询时,其结果就在这里高速缓存。

        shared pool的特点是有大量的小的(大约4KB)块内存。shared pool中的内存在LRU基础上管理。它类似于缓冲区高速缓存---如果不使用它,就将丢失它。有一个补充的程序包,妈DBMS_SHARED_POOL,它可以用来更改这个特性-----强制地将对象钉在共享池中。在数据库启动时,可以使用这个程序来装载频繁使用的过程和程序包。这样做,它们不会导致停止引用。通常,如果共享池中的内存片随着时间的失衡没有被重复使用,它就会老化,停止引用。即使是可能相当大的PL/SQL代码,也是在页面机制下进行管理,所以当运行非常大的程序中的代码时,只 有代码需要装载进小块的共享池。如果在扩展的时间璺上不使用它,而且共享池充满 了,其他的对象又需要空间时,它就会老化。

       不使用绑定变量(bind variable)是中断oracle共享池的最简单的方法。不使用绑定变量可以使系统性能下降,其中原因有:<1>系统花费了过量的cpu时间来分析查询。<2>系统消耗了极大 的资源来管理共享池中的对象,结果 是无法重用查询。

       如果提交给oracle的每一个查询是带有硬编码值的独特查询,那么共享池的概念是彻底失败的。设计共享池正是为了查询计划可以重复使用。如果每一个查询都 是崭新的,决不是前面见过的查询,那么高速缓存只是增加了额外开销。共享池就要抑制性能。试图解决这个问题的一个常见错误方法是xw共享池添加更多的空间,但它仅仅是把事情搞得比过去更糟。当共享池不可地又一次充满时,它获得了比小共享池相比更大的开销。其道理很简单,管理一个磊的充满 的共享池比管理小一点的充满的共享池要进行更多的工作-------这个总理的性正确解决方案是使用共享的SQL---重用查询。init.ora的参数SURSOR_SHARING,它可以在这个盘区中以短期的“支柱”方式来工作。但是此总理的惟一的解决方法是首先使用可重用的SQL。即使在最大的大型系统中,最多有10000~20000个不同的SQL语句。大部分的系统只插几百个不同查询。

      下面是关于共享池和init.ora参数SHARED_POOL_SIE的最后一个说明。在查询输出:

sql>select sum(bytes) from v$sgastat where pool='shered pool';

sum(bytes)

--------------

88085320

与SHARED_POOL_SIZE      init.ora参数:

sql> show parameter shared_pool_size\

NAME                          TYPE                    VALUE

------------------               -----------------        --------------

shared_pool_size         big integer            0

它们之间没有关系。

     这不同于这个事实:sum(bytes) from v$sgastat将问题大于shared_pool_size.共享池保存许多其他的结构,这些结构在init.ora参数对应的范围之外。在由sum(bytes)生成报表时,shared_pool_size参演是对共享池的最大贡献者。但它不是惟一 的贡献者。

7.大池

        大池不是因为它是一个“大”结构而得名的(虽然它在大小上可以非常大)。它的得名是因为它用来分配大块的内存,处理比共享池更大的内存。在它引入到oracle8.0之前,所有内存的分配都在共享池中进行。如果正在使用利用大内存分配 的特性,如MTS,寻是遗憾的。如果需要大量内存分配 的处理,以与共享池管理内存不同的方式使用内存,那么这更加令人困惑。如果需要大量内存分配的处理,以与共享池管理内存不同的方式使用内存,那么这更加令人困惑。共享池是在LRU基础上管理内存的,它对于高速缓存和重用数据是完美的。然而,大内存分配倾向于获得大块内存,使用大块内存,并随后 用大块内存来穿完成---没有高速缓存这些内存的需要。

       oracle所需要的是类似于为块高速缓冲区高速缓存而实现的回收(recycle)和保持(keep)缓冲区。这恰恰是大池离共享池的功能。大池是一个回收风格的内存空间,而共享池更类似于保持缓冲区池--如果人们要频繁地使用什么东西,那么 就将它高速缓存。

       在大池中分配 的内存是在堆中管理的,很像c语言借助malloc()和free()管理内存的方式。内存块一量被释放,它就可以被其他进程所使用。在共享池中,真的没有“释放”大块内存的概念。应该分配内存,使用内存,随后停止使用内存。之后,如果那个内存需要重用,oracle将停止引用该内存,块。只使用一个共享池带来的问题是,一种尺寸不是总能适合所有的情况。

下面对象使用大池:

<1>MTS--在SGA中分配UGA盘区。

<2>语句的并行执行(parallel execution of statements)--允许进程间消息缓冲区的分配,用来协调并行查询服务器。

<3>备份(back)--用于RMAN磁盘I/O缓存。

8.java  池

       java池在oracle8i数据库中是最新的池。用来支持数据库中JAVA的运行。如果 用java编写一个存储过程,或将EJB(enterprise java bean,企业级的javabean)放入数据库中,oracle将在处理这些代码的时候利用这些内存块。在oracle8.1.5中关于java池的早期的一个奇怪现象是:它不在show sga 命令中显示,且在v$sgastat视图中不见。这在当时是非常令人的,因为控制结构大小 的java_pool_size init.ora参数默认为20MB。这种疏忽已经使人们奇怪烦什么它的sga为数据库带来额外的20MB的RAM.然而,在8.1.6版本中,jav池在v$sgastat视图中是可见的,show sga命令中的可变容量也是可见的。init.ora参数java_pool_size用来确定为所有特定会话的java代码和数据所分配 java池的内存量。

     当在MTS模式下执行时,java池包括:<1>每个java类的共享部分<2>一些用于每个会话的会话状态 的uga,它们在sga中的java_pool中分开。其他的uga一般位于共享池中,或如果配置了大池,那么uga将在大池中分配。

    

 

       

   

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值