1       Oracle具有以下基本的内存结构

  1>    软件程序代码区

  2>    系统全局区

  3>    程序全局区

  4>    排序区

1.1    软件程序代码区(Software Code Area)

  软件程序代码区是一块用于存放那些正在运行和可以被运行的Oracle本身程序的内存区域,而这块内存区域是独立且受保护的区域,通常软件程序代码区的大小是固定的,只有在Oracle进行了版本升级或重新安装后才会改变。在不同操作系统下,这部分区域所要求的大小也不同。软件程序代码区的重点如下。

  软件程序代码区是只读的,可以被安装成共享的或非共享的,在可能的情况下,Oracle本身的程序是可共享的,这样所有的Oracle用户都可以直接使用这些程序,而不需要用户各自保存一份在自身的内存中,从而可以节省大量内存空间。如果一台服务器上有多个实例,这些实例可以使用同一个Oracle程序,这也就是为何当一台服务器上安装了一套Oracle软件后,可以使用这套软件配置多个Oracle数据库。

1.2    系统全局区(System Global Area)

1.2.1    概述

  之所以称为系统全局区(System Global Area,SGA),是因为其中的数据可以被Oracle所在的操作系统上的所有会话用户和程序共享,SGA有几个基本的特性,如下所示:

  1>   SGA由系统内存构成,其中存储了数据、用户信息和控制信息。

  2>   一个SGA只能服务于一个实例,也就是说,当一台服务器上有多个实例运行时,每个实例都有一个自己专用的SGA,虽然同一台服务器上SGA都是来自于操作系统上的内存,但实例之间不能相互访问对方的SGA。

  3>   SGA是共享的,当有多个用户使用到这个实例,SGA中的信息可以被所有用户同时使用,当然这牵涉了锁等问题。

  4>   Oracle进程和一个SGA就可以构成一个Oracle实例。当实例启动时,Oracle会自动从操作系统中分配设置好的内存给SGA,而当实例关闭时,操作系统就会回收这些内存。

  以下就是当实例启动后,显示已经分配了SGA的架构,如图2-1所示。

              图一:启动数据库实例

    解释:

      Total System Global Area:SGA的总大小

      Fixed Size:存储了SGA各部分组件信息,作为引导SGA创建的区域,此块区域就被固的

      Variable Size:共享池、Java池、大型池和流池等的配置总和

      Database Buffers:数据库高速缓冲区的大小。

      Redo Buffers:重做日志缓冲区的大小。

1.2.2    SGA的组成

  SGA的组成图如下:

  系统全局区由以下几部分组成

  1>   数据库高速缓冲区(Database Buffer Cache)

  2>   重做日志缓冲区(Redo Log Buffer)

  3>   共享池(Shared Pool)

  4>   Java池(Java Pool)

  5>   大型池(Large pool)

  6>   流池(Stream Pool)

  7>   固定SGA(Fix SGA)

1.2.2.1       数据库高速缓冲区(Database Buffer Cache)

  Oracle有一个很重要的概念,就是除非到了必要的时候,否则不会等待磁盘I/O,因为磁盘I/O是计算机系统运行中最慢的一个部分,所以,所执行的I/O越少越好数据库高速缓冲区(Database Buffer Cache)即是应此概念而规划出来的。

  数据库高速缓冲区的主要功能是用来暂时存放最近读取自数据库中的数据,也就是数据文件(Data File)内的数据,而数据文件是以数据块(Block)为单位,因此,数据库高速缓冲区中的大小是以块为基数。当用户通过应用程序第一次向Oracle数据库发出查询请求时,Oracle会先在数据库高速缓冲区内寻找该数据,如果有该请求所需要的数据,就直接从数据库高速缓冲区传回给用户,这称为缓存命中(Cache Hit),这样就可以减少硬盘上的I/O次数。如果Oracle发现用户要的数据并不在数据库高速缓冲区里,就称为缓存失误(Cache Miss),Oracle会从数据库中读取所需要的数据块,先放入数据库高速缓冲区中,再传送给用户,如图二所示。

图二:数据库高速缓冲区

  有关数据库高速缓冲区命中率的计算方式如下:

1 SELECT 1 - (PHY.VALUE / (CUR.VALUE + CON.VALUE)) "CACHE HIT RATIO"
2 FROM V$SYSSTAT CUR,
3      V$SYSSTAT CON,
4      V$SYSSTAT PHY
5 WHERE CUR.NAME = 'db block gets'
6   AND CON.NAME = 'consistent gets'
7   AND PHY.NAME = 'physical reads';

  解释:

  db block gets        :是指DML指令所得到的数据块个数。

  consistent gets     :是指查询指令得到的数据块个数。

  logical reads          :将db block gets与consistent gets相加得到的数据块个数。

  physical reads       :实际从硬盘中读出的数据。

  提示

        利用以上的查询获取缓存命中率(HIT RATIO)最好要大于90%。

        以上的查询命中率以整个数据库高速缓冲区为主。

  数据库高速缓冲区中包含三种不同性质的缓存:

Dirty Buffer

这里的Buffer中存放的是已修改,但尚未写入数据库的数据。

Free Buffer

这里的Buffer是指其中的内容和数据库内的内容是一模一样的,也就是这些Buffer已经写入数据库内,随时可以拿来覆盖重复使用。

Pinned Buffer

这里的Buffer是指正在被使用的Buffer。

  数据库高速缓冲区是利用两种List来管理内部三种不同性质的Buffer

Dirty List

包含Dirty Buffer,主要是将准备写入数据库的数据,在适当的时机写入

LRU List

包含Free Buffer、Dirty Buffer、Pinned Buffers

Oracle对于数据库高速缓冲区的使用方式是利用后台进程的DBWRn写入数据文件内,而DBWRn将Dirty Buffer从数据库高速缓冲区取出再写到数据文件内,主要是通过两种方式:先期写入协议机制和LRU机制。

1.2.2.2       重做日志缓冲区(Redo Log Buffer)

  Oracle重做日志的概念是记录每个数据块插入某个值或者删除某个值的语句。假设某个Update语句更新了10个数据块,则按照Oracle重做日志的概念,会针对每个数据块记录一对删除旧值和插入新值的语句,因为有10个数据块,所以会有10对类似的语句被记录下来。而为了减少I/O的次数,Oracle在内存结构里的系统全局区中,划分一块内存块专门存放这些变更的数据,即日志缓冲区(Redo Log Buffer),所以说,重做日志缓冲区是用来跟踪并记录最近变更过的数据记录的。这里所指的变更是包含DML与DDL的语句:Insert、Update、Delete、Create、Alter,以及Drop,即在数据库高速缓冲区中所做的变更,都会产生重做日志,而这些变更的数据都在内存中的重做日志缓冲区中以Redo Entry的方式存储。Redo Entry是Oracle从用户会话占用的内存里将这些变更的记录复制到重做日志缓冲区内,其在内存中是一段连续的内存块,Oracle利用后台进程中的LGWR在适当的时机将重做日志缓冲区中的信息写回到联机重做日志文件内,以便万一数据库崩溃,可以进行必要的恢复。后台进程LGWR将Redo Entry写回到联机重做日志文件的时机如下:

  1>   用户执行commit指令,触发LGWR将Redo Entry写到联机重做日志文件内。

  2>   先期写入协议机制,此原理是在后台进程DBWR将脏缓冲区写回到数据文件之前,也就是在执行检查点作业前,重做日志缓冲区内相关的Redo Entry都必须完成写入动作,以备不时之需;如果DBWR发现某些Redo Entry尚未写入联机重做日志文件,就会通知LGWR前来处理。Oracle会定期执行检查点操作,以保证数据文件的内容与联机重做日志文件的内容一致。

  3>   LGWR每隔三秒会确认一下重做日志缓冲区内的空间,当使用空间超过1/3时,触发LGWR,将Redo Entry写回到联机重做日志文件内。

  4>   重做日志缓冲区内的数据达到1 MB,触发LGWR,将Redo Entry写到联机重做日志文件。

  5>   发生联机重做日志切换(Log Switch)时,触发LGWR,将Redo Entry写到联机重做日志文件

  使用以下方式来查询重做日志缓冲区内的块大小。

  select distinct lebsz as redo_block_size from v$kccle;

  重做日志缓冲区的重要参数主要有以下两项,下面分别进行说明。

    1> LOG_BUFFER  :决定了重做日志缓冲区的大小。

    2> _LOG_IO_SIZE : 默认值是重做日志缓冲区的1/3,即当重做日志缓冲区内的空间有1/3写满时,Oracle就会启动LGWR,将Redo Entry写入联机重做日志文件。设置此参数主要是调整这个1/3的值。设置一个较低的LOG_IO_SIZE的值,可以减缓日志文件同步(Log File Sync)的问题;设置一个较高的_LOG_IO_SIZE的值,可以解决日志缓冲区空间(Log Buffer Space)等待事件的问题。

1.2.2.3       共享池(Shared Pool)

       共享池就是Oracle缓存一些“程序”的地方。

其结构如图2-33所示,以下并分别对其进行说明。

                                 图2-33  共享池

一:库缓存

  在库缓存中包括共享SQL区域、PL/SQL(过程和包)以及控制结构如锁、内存句柄等。

  共享SQL区域:当执行一个SQL语句时,Oracle就会为每一句SQL打开一个游标(Cursor),并提供一个共享SQL区域和私有SQL区域空间用于存放,当发现两个以上的会话在使用同一个SQL语句时,Oracle就会重新组织共享SQL区域,使这些会话用户能重复使用此区域的内容,从而不浪费宝贵的资源,同时,还会在私有SQL区域里保存一份这个SQL语句的副本;反之,如果没有找到相同的SQL语句,就必须重新进行完整的分析作业,并将分析树(Parse Tree)以及执行计划等存放在共享池内,以备下次使用。这时要注意的是,在Oracle于共享池中寻找相同的SQL语句的过程中,如果使用的SQL语句有任何一个地方不相同,Oracle就会将此SQL语句视为在此共享池中找不到,所以需要重新进行分析。因此,如果同一段SQL语句只是在条件的部分输入不同的值,Oracle也会认为SQL语句不同,可使用绑定变量,意思是Oracle会将变动的值视为绑定变量,这样很容易在共享池里找到相同的SQL语句

当一条新的SQL语句被分析时,Oracle从共享池中分配一块内存来存储共享SQL区域,而这块被分配的内存的大小与这条语句的复杂性相关,如果共享池中的空间不够分配给共享SQL区域使用,Oracle就会启动LRU机制,将最近最少使用的内存块释放出来,直到有足够的空间分配给新SQL语句的共享SQL区域;被释放出来的那块内存块内的SQL语句,如果再次被使用就必须重新分析,并重新分配共享SQL区域,而这些动作都是比较消耗CPU的作业。这就是为何要使用绑定变量的原因了。因为如果没有使用绑定变量,当SQL语句中的变量的数值不同时,Oracle就会将其视为一条新的语句,重复上面的分析、内存分配等动作,这都将大大消耗系统资源,降低Oracle系统性能。

  PL/SQL过程和包:Oracle对于PL/SQL过程、函数、触发器、包等处理过程和上述的SQL语句处理过程与方式相同,都会分配一个内存来存储被分析、编译过的过程、函数、触发器、包等。同时分配一个私有SQL区域空间来存放运行中的程序值、变量、所需内存等的相关信息等。如果是多个会话同时使用同一个PL/SQL程序,那么除了会共享一个程序之外,在其各自的私有SQL区域中还会保留一份,主要用于存储会话的变量值。

在PL/SQL程序里的SQL语句会当成普通的SQL语句处理,也就是说,Oracle会为这些PL/SQL程序里的SQL语句提供一个共享SQL区域和私有SQL区域空间用于存放。

二:数据字典高速缓存

  数据字典高速缓存是有关于数据库的参考信息、数据库的组织结构和数据库中的用户信息与权限等,而这些内容都是存储在表内,通常以表和视图的形式进行呈现,就像经常使用到的V$xx、DBA_xx等系统的视图和表都是存储在数据字典(Data Dictionary)内。值得注意的是,当SQL语句在分析的过程中时,也会去参考数据字典内的信息,而参考数据字典的动作所产生的SQL语句称为递归的SQL,如果使用Statspack分析统计数据,此类的递归的SQL会被统计为Recursive Calls。

1.2.2.4       Java池(Java Pool)

  Java池也是SGA中的一块可选内存块,它也属于SGA中的可变区域,Java池的内存用于存储所有会话中特定Java程序代码和JVM中的数据,与数据库高速缓冲区和共享池相同,在Oracle 10g以后,提供了一个新的Java池的建议功能,以辅助调整Java池的大小,而建议的统计数据可以通过视图V$JAVA_POOL_ADVICE来查询。Java池建议功能的使用方式与数据库高速缓冲区建议功能类似。

  Java池的参数分别说明如下。

  JAVA_POOL_SIZE此参数可指定Java程序所使用的最大内存量,也就是此参数可限制用于存储每次数据库所使用的Java状态,如果用户会话的Java状态超过了该值,该会话就会由于内存不足而终止。

  其设置方式:JAVA_MAX_SESSIONSPACE_SIZE = integer

1.2.2.5       大型池(Large pool)

  大型池(Large Pool)是SGA中的一块可选内存块,同时,大型池的功能类似共享池的内存缓冲区。与共享池不同的是,大型池只在特殊的情况下才会使用。

  在以下情况会需要大型池

    1>   在多线程服务器(Multi-Threaded Server,MTS)下,把大型池分配给用户,以使会话可以进行排序(Sort Area)及哈希运算(Hash Area)。

    2>   使用并行操作查询(Parallel Query)时。

    3>   作为大型连续文件的I/O的缓冲区。

    4>   使用Oracle RMAN时,大型池为其I/O缓冲区。

大型池是属于SGA的可变区域(Variable Area),但大型池并不属于共享池,大型池最大为4 GB。

并行操作查询使用大型池作为内存缓冲区是从Oracle 8i版本开始的,当参数PARALLEL_AUTOMATIC_TUNING设置为TRUE时,并行操作查询在大型池中分配缓冲区空间。在Oracle 9i中,大型池还被用来存储Oracle XA的相关信息。大型池也使用共享池的闩锁机制,但和共享池不同的是,大型池并不使用LRU机制,而是使用Large Memory Latch的保护,因此,大型池中缓冲区内的数据不会被置换出来,而大型池内的数据会利用用户的会话来控制分配和释放大型池的空间。如果大型池的空间不足,将出现ORA-4031错误。如果Oracle设置了大型池,那么,多线程服务器只会在大型池中分配UGA空间;如果没有设置大型池,则在共享池内分配空间。

如果没有设置大型池,那么大型池的默认值为0。在一般情况下,大型池的使用需求不大,因此,不必设置过大的大型池。

大型池的重要参数说明如下:

LARGE_POOL_SIZE:参数用以设置大型池的大小,其值必须大于512 KB,这和操作系统有关。

      设置方式:LARGE_POOL_SIZE = INTEGER [K | M]

_LARGE_POOL_MIN_ALLOC:在大型池中的空间是分段申请的,每段申请的最小值是由LARGE_POOL_MIN_ ALLOC决定的,此参数的范围是16 KB~64 MB,而默认值为16 KB。

             设置方式:_LARGE_POOL_MIN_ALLOC = INTEGER [K | M]

PARALLEL_AUTOMATIC_TUNING:参数主要用于打开并行操作查询。

             设置方式:PARALLEL_AUTOMATIC_TUNING = TURE/FALSE

1.2.2.6       流池(Stream Pool)

  流池(Streams Pool)是Oracle 10g中的新增功能,主要提供专门的Stream复制功能,流池可选用内存块,它也属于SGA中的可变区域。如果在配置10g数据库时,没有特别指定此块区域,那么Oracle会在第一次使用Stream复制功能时自动建立此块区域。如果自动建立,Oracle会先确认是否设置了SGA_TARGET参数,如果有,Oracle会从系统全局区中(SGA)中分配内存给流池;如果没有指定SGA_TARGET,则会从数据库缓冲区内划分一部分内存过来给流池。而此类分配的大小是共享池大小的10%,同样,Oracle也提供了一个流池的建议功能,来协助调整流池的大小,而建议的统计数据可以通过视图V$STREAMS_ POOL_ADVICE来查询。流池建议功能的使用方式与数据库缓冲区指导功能类似。

流池的参数说明:

  STREAMS_POOL_SIZE:指定流池的大小,如果设置为0,当第一次使用Stream复制功能时,Oracle会自动建立此块区域,而自动建立的大小为共享池大小的10%。

     设置方式:STREAMS_POOL_SIZE = INTEGER [K | M]

1.2.2.7       固定SGA(Fix SGA)

固定SGA是SGA的一个组件,其大小因系统和版本而异。安装时,固定SGA会“编译到”Oracle二进制可执行文件本身当中(所以他的名字有固定一词)。在固定SGA中,有一组指向SGA其他组件的变量,还有一些变量中包含了各个参数的值,我们无法控制固定SGA的大小,但是通常固定SGA都很小。可以把这个区想成Oracle中的“自启动”区,Oracle在内部要使用这个区来找到SGA的其他区

1.3    程序全局区(Program Global Area)

  进程全局区(PGA)是特定于进程的一段内存。换句话说,这是一个操作系统进程或线程专用的内存,不允许系统中的其他进程或线程访问。PGA一般通过C语言的运行时调用malloc()或memmap()来分配,而且可以在运行时动态扩大(甚至可以收缩)。PGA绝对不会在Oracle的SGA中分配,而总是由进程或线程在本地分配。

  实际上,对你来说,用户全局区(UGA)就是你的会话的状态。你的会话总能访问这部分内存。UGA的位置完全取决于你如何连接Oracle。如果通过一个共享服务器连接,UGA肯定存储在每个共享服务器进程都能访问的一个内存结构中,也就是SGA中。如果是这样,你的会话可以使用任何共享服务器,因为任何一个共享服务器都能读写你的会话的数据。另一方面,如果使用一个专用服务器连接,则不再需要大家都能访问你的会话状态,UGA几乎成了PGA的同义词;实际上,UGA就包含在专用服务器的PGA中。查看系统统计信息时可以看到,采用专用服务器模式时,总是会报告UGA在PGA中(PGA大于或等于所用的UGA内存;而且PGA内存的大小会包括UGA的大小)。

  所以,PGA包含进程内存,还可能包含UGA。PGA内存中的其他区通常用于完成内存中的排序、位图合并以及散列。可以肯定地说,除了UGA内存,这些区在PGA中的比重最大。

  从Oracle9i Release 1起,有两种办法来管理PGA中的这些非UGA内存:

  • 手动PGA内存管理,采用这种方法时,你要告诉Oracle:如果一个特定进程中需要排序或散列,允许使用多少内存来完成这些排序或散列。
  • 自动PGA内存管理,这要求你告诉Oracle:在系统范围内可以使用多少内存。

  分配和使用内存的方式因情况不同而有很大的差异,因此,我们将分别进行讨论。需要说明,在Oracle9i中,如果采用共享服务器连接,就只能使用手动PGA内存管理。这个限制到Oracle 10g Release 1(及以上版本)中就没有了。在Oracle 10g Release 1中,对于共享服务器连接,既可以使用手动PGA

  内存管理,也可以使用自动PGA内存管理。

  PGA内存管理受数据库初始化参数WORKAREA_SIZE_POLICY的控制,而且可以在会话级修改。在Oracle9i Release 2及以上版本中,这个初始化参数默认为AUTO,表示自动PGA内存管理。而在Oracle9i Release 1中,这个参数的默认设置为MANUAL。

1.4    排序区

排序所需要的内存空间,Oracle利用该内存区排序数据,这部分空间则称为排序区,排序区在于请求排序的用户进程的内存中,该空间的大小为适就排序数据量的大小,可增长,但受初始化参数SORT_AREA_SIZE所限制

转载于:https://www.cnblogs.com/renjie08317/archive/2012/10/26/2740811.html

Oralce的内存结构相关推荐

  1. ORACLE内存结构简介

    ORACLE数据库作为世界上一款功能强大的数据库管理软件,功能体系特别庞大.我们有必要对它的每一部分学习了解,然后才从全局的角度进行有效把握.我们会着重从理论基础体系角度再逐步到实战应用.实际上,如果 ...

  2. 从内存溢出看Java 环境中的内存结构

    作为有个java程序员,我想大家对下面出现的这几个场景并不陌生,倍感亲切,深恶痛绝,抓心挠肝,一定会回过头来问为什么为什么为什么会这样,嘿嘿,让我们看一下我们日常在开发过程中接触内存溢出的异常: Ex ...

  3. [二]Java虚拟机 jvm内存结构 运行时数据内存 class文件与jvm内存结构的映射 jvm数据类型 虚拟机栈 方法区 堆 含义...

    前言简介 class文件是源代码经过编译后的一种平台中立的格式 里面包含了虚拟机运行所需要的所有信息,相当于 JVM的机器语言 JVM全称是Java Virtual Machine  ,既然是虚拟机, ...

  4. 0x00000000指令引用的内存不能为written_jvm的内存结构

    Jvm的内存结构是理解jvm的基础,下面我用最浅显易懂的语言来分析一下jvm的内存结构,jvm内存分为五大块: 一:程序计数器:程序计数器是用来指示当前线程要执行哪条指令,并且在执行完该条指令后让程序 ...

  5. 玩点深入的:Java 虚拟机内存结构及编码实战

    本文来源:不会coding 了解JVM内存结构的目的 在Java的开发过程中,因为有JVM自动内存管理机制,不再需要像在C.C++开发那样手动释放对象的内存空间,不容易出现内存泄漏和内存溢出的问题. ...

  6. JVM内存结构、内存模型 、对象模型那些事

    作者:Hollis,阿里资深攻城狮 来自:Hollis Java作为一种面向对象的,跨平台语言,其对象.内存等一直是比较难的知识点.而且很多概念的名称看起来又那么相似,很多人会傻傻分不清楚.比如本文我 ...

  7. Jvm 系列(二):Jvm 内存结构

    所有的Java开发人员可能会遇到这样的困惑?我该为堆内存设置多大空间呢?OutOfMemoryError的异常到底涉及到运行时数据的哪块区域?该怎么解决呢?其实如果你经常解决服务器性能问题,那么这些问 ...

  8. 运行时常量池在哪里_Java虚拟机详解(二)------运行时内存结构

    首先通过一张图了解 Java程序的执行流程: 我们编写好的Java源代码程序,通过Java编译器javac编译成Java虚拟机识别的class文件(字节码文件),然后由 JVM 中的类加载器加载编译生 ...

  9. 转:JAVA常见错误处理方法 和 JVM内存结构

    OutOfMemoryError在开发过程中是司空见惯的,遇到这个错误,新手程序员都知道从两个方面入手来解决:一是排查程序是否有BUG导致内存泄漏:二是调整JVM启动参数增大内存.OutOfMemor ...

最新文章

  1. 保研计算机英语词汇,实用英语口语:“保研”怎么说?
  2. OpenCV中的cvCreateImage的参数channels()的意义
  3. CSS样式中” 大于号”
  4. 想不到,三级缓存是这样解决循环依赖的……
  5. java executor解读_Java-多线程框架Executor解读
  6. C#中的StringBuilder类
  7. 她,18岁,李飞飞三度公开表扬,高中时NIPS获奖,创造「AI手术教练」
  8. leetcode-40-组合总和 II
  9. 关于深度学习caffe for Windows编译入门
  10. c语言程序设计教程上海交通,C语言程序设计教程 交通学习文学.pdf
  11. cisco 3750G 冗余备份
  12. php实现12306验证码,PHP仿12306点图验证码
  13. 从几个简单例子聊聊Verilog的参数化设计(parameter、localparam和`define)
  14. 转帖自勉:一个猎头的自述
  15. 今天公司HR推荐了一个人来应聘财务经理
  16. App地推:这些方法让你事半功倍
  17. 电磁场与仿真软件(36)
  18. 9、RH850 SPI(CSIH) 通讯功能和配置
  19. Libgdx slg游戏进程记录
  20. Unity中利用动画机(Animation) 制作物体的爆炸拆解

热门文章

  1. 学Python可以用来干什么?就业情况究竟怎么样?
  2. 卷积神经网络CNN如何训练?
  3. numpy.random随机数模块常用函数总结
  4. 几个实例让你轻松理解正则表达式
  5. 问答系统设计的一些思考
  6. CNN看清世界——浅谈四个经典网络的差异
  7. @scheduled注解配置时间_@Scheduled注解
  8. java 内存分析 ibm_IBM内存检测工具(IBM Thread and Monitor Dump Analyzer for Java)
  9. 走进android的世界(不断更新中)
  10. 【GPU加速系列】PyCUDA(一):上手简单操作