内存结构

本文详细介绍了Oracle数据库的内存结构,包括SGA(System Global Area)的各个组件,如Database Buffer Cache、Redo Log Buffer、Shared Pool等,以及PGA(Program Global Area)和UGA(User Global Area)的作用。讲解了缓冲区的状态、访问模式和I/O操作,强调了内存管理在优化数据库性能中的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

内存结构,如下图:


一、SGA

SGA组件除了Log buffer之外,空间的分配与释放所基于的基本单位都是granules,granules的大小是基于操作系统和SGA的大小。

1、Database Buffer Cache

Database Buffer Cache也叫buffer cache,保存从数据文件中读取的数据块。buffer cache可以实现下面两个目标:

  • 优化物理I/O:当语句COMMIT之后,redo records会被刷新到日志文件中,但是脏缓存并不会马上被刷新到数据文件中,而是保存在buffer cache中。DBWn进程会每三秒刷新一次脏缓存到数据文件。
  • 把频繁使用的数据块保存到buffer cache中,把不是很频繁使用的数据块刷新到数据文件中:当Database Smart Flash Cache (flash cache) 启用的时候,部分的buffer cache被保存到flash cache。flash cache位于叫flash disk device的固体状态存储设备。这样就避免了从磁盘中读取数据,而是从flash memory中读取。不过,Database Smart Flash Cache只是用于 Solaris 和 Oracle Enterprise Linux操作系统。

1.1、Buffer States

有三种状态:

  • unused:该状态下的缓存数据块没有被使用过;
  • Clean:拥有数据但是处于一致性状态,也就是已经被刷新到了数据文件,CKPT不会对其进行检查点操作;
  • Dirty:还没有被刷新到数据文件的脏缓存。

每个缓冲块都有两种访问方式:pinned或free.多个会话不能同时对处于pinned状态的缓存块进行访问。为了更有效率地访问数据库缓存,ORACLE使用 least recently used (LRU) list,一端的cold buffer不会经常被访问,而另一端的hot buffer则会经常被访问。为了并发性,ORACLE 会用多个least recently used (LRU) list。

1.2、Buffer Modes

  • Current mode:也叫db block get ,数据库经常在修改操作的时候使用db block get,只会修改当前版本的数据块。
  • Consistent mode:也叫consistent read get,当需要读取正在被修改的数据块缓存的时候,会使用undo data来让其访问修改前版本的数据块。

1.3、Buffer I/O

  • Buffer Reads

buffer search如下图:


其中,第一步对buffer cache的检索叫 logical read,第二步对于flash cache的检索叫optimized physical read,而第三步对于磁盘物理文件的读取叫physical read。

若在第一步的时候找到了所需要的缓冲块,则叫cache hit ,否则叫cache miss。可以使用buffer cache hit ratio来衡量数据库不用从磁盘中读取数据块的频率。

  • Buffer Writes :DBWn把不常用的脏缓存写入到物理文件中。
  • Buffer Touch Counts:该机制用来描述LRU LIST数据缓存块被访问的频繁程度,若一缓存块被spin而不是constantly shuffling buffers 则该缓存块的touch count增加一次。需要注意的是,在缓存块发生spin的三秒钟之后才会使得touch count增加。该机制避免了burst of pins。比如说,对同一数据块插入多行也只是视为发生了一次touch。若一数据缓存块在LRU LIST的cold端,而其touch count非常高,则该块的指针就会修改到LRU LIST的hot端。数据库不会移动缓存块的位置,而是修改LRU LIST的位置指针。
  • Buffers and Full Table Scans:当必须从数据文件中读取数据的时候,数据库会插入这些缓存块到LRU LIST的中部,这样可以避免需要重新从数据文件中读取那些被频繁使用的数据块。当时,对于全表扫描,如果扫描所读取的数据块比数据块缓存还要大,则会导致频繁使用的数据缓存块被覆盖重写。此时,数据库对于全表扫描采用了不同于其他的一种方式,全表扫描的这些数据块会马上被重用,以避免清空缓存问题的出现。不过,如果默认的行为并不是你所想要的话,可以在创建表的时候设置CACHE参数。此时,数据库不会pin the blocks.

1.4、Buffer Pools

Buffer Pools 是一组缓冲的集合。database buffer cache被分成一个或多个buffer pools.如下图:

  • Default pool:读入的数据块正常情况下会被缓存在这里;
  • Keep pool:其是为那些经常被访问的缓存数据块所留的,不过当空间不足的时候会age out Default pool。其目的是保留这些对象在内存中,从而避免不必要的I/O操作;
  • Recycle pool:其是为那些经常被使用的缓存数据块所预留的。其可以避免这些对象消耗不必要的空间。
  • 另外还有一些数据块大小不是DB_CACHE_SIZE大小的数据块保存区域。

2、Redo Log Buffer


redo log buffer保存了DDL或DML语句所产生的redo records。LGWR总是先于DBWn把redo records写入到online redo log中。

3、Shared Pool


3.1、Library Cache

正如上图所示Library Cache包括了shared SQL area和private SQL area(只是在shared server模式下存在)两部分。其中,Library Cache保存的是解析的SQL语句、解析树、执行计划和PL/SQL程序单元。

当一个新的SQL语句被解析的时候,数据库就会为其分配新的shared pool内存,分配的大小取决于语句的复杂度。

在下面的情况下,一个SQL语句的shared SQL area的内存空间会被删除或无效。

  • LRU中所对应的最不常被使用的shared SQL area的内存就会被释放;
  • 如果统计数据是从表、聚集表或索引中收集来的,在默认情况下数据库会在一段时间之后逐步删除包含对象的shared SQL area内存空间;
  • 如果SQL语句所引用的对象由于DDL语句被修改了定义,则这些shared SQL area就会无效;
  • 如果你改变了数据库的global name,则整个shared pool都会被清空;
  • ALTER SYSTEM FLUSH SHARED_POOL语句的提出;

3.2、Data Dictionary Cache:以row cache的方式(而不是buffer)保存用过的数据字典对象;

3.3、Server Result Cache

在这里,其保存的是结果集而不是数据块。

  • SQL Query Result Cache:保存的是SQL语句的结果,当有事务修改了构成该结果集对象的数据或元数据,则相应的结果集将会变成无效。可以在语句中使用RESULT_CACHE hint来指示数据库语句使用其中的结果集。而RESULT_CACHE_MODE则决定了SQL Query Result Cache是由所有的语句使用,还是只是哪些添加了注释的语句所使用;
  • PL/SQL Function Result Cache:保存函数的结果集(对应参数和结果集),如果形成结果集的对象被修改了,则相应的结果集也会无效,需要重新计算。

另外,需要注意的是,client result cache是应用程序级别的结果保存。其保存在客户端。

3.4、Reserved Pool

该内存的作用用技术文档的话语来说就是allocate large contiguous chunks of memory。以chunk的形式,可以允许大对象(超过5KB)被加载到内存而不是请求一个临近区域。这种方式可以避免因为碎片而用完临近内存的情况出现。在很少情况下,Java, PL/SQL, 或者SQL cursors会要求超过5KB的共享池内存。为了让这些分配的空间更有效,数据库会分割一些shared pool给Reserved Pool。

4、Large Pool

大池可以为下面的操作或结构提供大量的空间:

  • 共享服务器模式下的UGA结构,还有就是Oracle XA接口;
  • 并发执行语句的信息缓存;
  • RMAN I/O slaves;

大池不是根据LRU LIST来释放内存。大池中的内存被分配之后直到不在被使用。为此,会有大量的内存被释放,其他进程就可以使用。

5、Java Pool

Java Pool保存的数据为JAVA代码以及JVM中的数据。

6、Streams Pool

Streams Pool为ORACLE流所使用,其存储的是缓冲队列信息,同时为ORACLE stream捕获进程和应用进程提供内存空间。

7、Fixed SGA

Fixed SGA是一个内部管理区域。比如,Fixed SGA包括下面的内容:

  • 关于数据库和实例状态的通用信息;
  • 进程间的通讯信息,如LOCK;

8、Software Code Areas

Software Code Areas用来存储正在运行或能够被运行的代码,如ORACLE DATABASE CODE.

二、PGA



1、private SQL Area

当会话开始的时候,会产生一个cursor,该cursor是PGA中private SQL Area的名称或handle,可以理解为其实客户端的一个指向服务器端的指针,以及在服务器端的一个声明。该区域有客户端负责管理,虽然服务器端有OPEN_CURSOR实例参数来限制会话的数量。

  • The run-time area:执行请求的第一步就是创建The run-time area,来保存该SQL语句以及语句被执行的状态信息,如全表扫描所查找行的数目;该区域在SQL语句结束的时候被释放;
  • The persistent area:该区域保存了会话期间所有的bind variable.该区域在会话结束的时候被释放。

2、Session Memory:即下面要说的UGA,存在于detected server模式中。

3、SQL Work Areas

  • Sort Area:对行集进行排序;
  • Hash Area:hash join操作会使用Hash Area来创建hash table;
  • Bitmap Merge Area:Bitmap Merge操作使用Bitmap Merge Area操作来合并从Bitmap index中查找到的数据;

三、UGA:


以上为UGA的结构主件。UGA是一个会话内存,其必须在整个会话周期内有效。为此,在shared server模式下,必须在SGA中,因为PGA对应的是一个进程,该进程是对应多个会话的。而在dedicated server模式下,其存在于PGA中。如上图所示,UGA中包括了两部分的信息:

  • Session Variables:为一个会话所需要的信息,如logon信息等。若该会话调用了PL/SQL包,则UGA会包括package state,即在某一特定时间包的参数值;
  • OLAP Pool:当用户访问维度对象如cube的时候,一个OLAP会话就已经自动启动,同时会在OLAP Pool中分配OLAP page(相当于data block),以保存相关的信息,该OLAP page会在会话期间一直存在。

---------------------------------------------------------------------------------------------------
如有错误,欢迎指正
技术交流QQ:1732035211
技术交流邮箱:1732035211@qq.com
新浪微博:数据库小菜鸟http://weibo.com/u/3132578390
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值