书名书名书名书名书名书名书名书名书名书名书名书名书名书名
2 * (select value from v$parameter where name='db_block_size') / 1024 /1024 Buffer_Cache_MB 3 from dual; BUFFER_CACHE_MB --------------- 195.3125
从Oracle9i开始,Oracle引入了一个新的初始化参数db_cache_size ,该参数用来定义主Block Size(db_block_size定义的块大小)的Default缓冲池的大小。
db_cache_size最小值为一个粒度(Granule)。
粒度也是Oracle9i引入的一个新的概念,是连续虚拟内存分配的单位,其大小取决于估计的SGA 的总大小(SGA 总大小由SGA_MAX_SIZE 参数得到):
u? 如果估计的SGA 大小< 128 MB 则值为4 MB u? 否则值为16 MB(32位Windows为8M)
在Oracle10gR2中,Granule的分配算法有所改变,在大多数平台上:
u? 如果SGA<1G,Granule通常为4M
u? 否则Granule为16M(32位Windows为8M)。
这个Granule大小受到一个内部隐含参数_ksmg_granule_size的控制,以下是Oracle9iR2中的测试输出(不同版本可能不同):
SQL> select * from v$version where rownum <2; BANNER
---------------------------------------------------------------- Oracle9i Enterprise Edition Release 9.2.0.4.0 - Production SQL> show parameter sga_max_size
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------ sga_max_size big integer 219223120 SQL> @GetParDescrb.sql
Enter value for par: _ksmg_granule_size
NAME VALUE DESCRIB
------------------------------ -------------------- --------------------------- _ksmg_granule_size 16777216 granule size in bytes SQL> alter system set sga_max_size=120M scope=spfile; System altered. SQL> startup force;
SQL> show parameter sga_max_size
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------ sga_max_size big integer 126948772 SQL> @GetParDescrb.sql
Enter value for par: _ksmg_granule_size ·26·
第1章 章名章名章名章名章名
NAME VALUE DESCRIB
------------------------------ -------------------- ----------------------------- _ksmg_granule_size 4194304 granule size in bytes
各内存组件所使用的Granule大小可以通过动态性能视图来查询:
SQL> select component,granule_size from v$sga_dynamic_components; COMPONENT GRANULE_SIZE -------------------- ------------ shared pool 16777216 large pool 16777216 buffer cache 16777216
大家知道内存空间总是有限的,Oracle管理Buffer Cache使用的是LRU算法,但是这又带来另外一个问题,很多批处理的操作(比如全表扫描等)可能会导致Buffer Cache的刷新,将经常使用的数据“挤出”Buffer Cache,在不同版本中,Oracle不停的改进LRU算法,以避免这类操作的过度影响。
但是在此之外,Oracle提供了Buffer Cache的多缓冲池技术从另外一个方面来解决这个问题。所谓的多缓冲池技术是指,根据不同数据的不同访问方式,将Buffer Cache分为Default、Keep和Recycle池三个部分。对于经常使用的数据,我们可以在建表时就指定将其存放在Keep池中;对于经常一次性读取使用的数据,可以将其存放在Recycle池中;Keep池中的数据倾向于一直保存,Recycle池中的数据倾向于即时老化,而Default池则存放未指定存储池的数据,按照LRU算法管理。
默认情况下,所有表都使用DEFAULT池,它的大小就是数据缓冲区Buffer Cache的大小,由初始化参数db_cache_size(8i中是db_block_size*db_block_buffers)决定。
如果我们在创建数据表或修改数据表时指定STORAGE (BUFFER_POOL KEEP)或者STROAGE(BUFFER_POOL RECYCLE)语句,就设置了这张表使用KEEP或者RECYCLE缓冲区。这两个缓冲区的大小分别由初始化参数db_keep_cache_size和db_recycle_cache_size来决定。
在Oracle8i中,只能修改参数文件,然后重新起动数据库,才能使对这两个参数的修改生效。在Oracle9i中,可以动态修改,下面看一下Oracle9i中这几个参数的设置:
SQL> show parameter cache_size
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------ db_16k_cache_size big integer 0 db_2k_cache_size big integer 20971520 db_32k_cache_size big integer 0 db_4k_cache_size big integer 0 db_8k_cache_size big integer 0 db_cache_size big integer 4194304 db_keep_cache_size big integer 0
·27·
书名书名书名书名书名书名书名书名书名书名书名书名书名书名
db_recycle_cache_size big integer 0 SQL> alter system set db_keep_cache_size=4M; System altered.
SQL> alter system set db_recycle_cache_size=4M; System altered.
SQL> show parameter cache_size
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------ db_16k_cache_size big integer 0 db_2k_cache_size big integer 20971520 db_32k_cache_size big integer 0 db_4k_cache_size big integer 0 db_8k_cache_size big integer 0 db_cache_size big integer 4194304 db_keep_cache_size big integer 4194304 db_recycle_cache_size big integer 4194304
同时还可以看到,在Oracle9i中存在一系列的db_nk_cache_size参数,这是Oracle9i中引入的多块大小支持。Oracle9i允许在同一个数据库中存在多种Block_size的表空间,分别支持:2k,4k,8k,16k和32k 的Block_size,其中,由db_block_size定义的块大小被称为主Block_size。
如果在数据库中创建不同block_size的表空间则需要分别设定db_nk_cache_size参数。 各缓冲池的设置,我们可以通过查询v$buffer_pool得到:
SQL> select id,name,block_size,current_size,target_size from v$buffer_pool; ID NAME BLOCK_SIZE CURRENT_SIZE TARGET_SIZE ---------- -------------------- ---------- ------------ ----------- 1 KEEP 8192 4 4 2 RECYCLE 8192 4 4 3 DEFAULT 8192 4 4 4 DEFAULT 2048 20 20
2.Shared Pool
Shared Pool通常被称为共享池,包含共享内存结构,如SQL区等。SQL区包含SQL解析树、执行计划等信息,通过共享池,反复执行的SQL可以在不同Session间得到共享。
共享池的大小由参数shared_pool_size 定义,在Oracle9i中,最小值为一个Granule大小。 关于共享池的设置和优化是非常重要和复杂的,我们将在下一章进行专题探讨。 3. Redo Log Buffer
Redo Log Buffer-日志缓冲区存储重做日志条目(redo entries),日志记录数据库变更,最终将被写出到重做日志文件中,在数据库崩溃或故障时用于恢复;如果数据库运行在归档模式下,最终日志文件还会被写出到归档日志中,这些归档可以在介质恢复时用于进行数据恢复。
·28·
第1章 章名章名章名章名章名
日志缓冲区的大小由初始化参数log_buffer决定。这是一个静态参数,不能动态调整。 4. 其他内存组件
Large Pool-大池是SGA的一个可选组件,通常用于共享服务器模式(MTS)、并行计算或RMAN的备份恢复等操作。
Java Pool-Java池主要用于JVM等Java选件。
Streams Pool-Streams pool是Oracle10g引入的概念,为Oracle的Streams功能所使用,如果不定义该参数,这部分内存将从Shread Pool中分配。
从下图我们可以看一下Oracle SGA的组成:
对于SGA各部分内存分配,可以从数据库的视图中查询得到(在SQL*Plus中通过命令show sga也可以看到同样结果):
SQL> select * from v$sga; NAME VALUE -------------------- ---------- Fixed Size 731632 Variable Size 268435456 Database Buffers 117440512 Redo Buffers 811008
在Oracle9i中,Variable Size 包括shared_pool_size,java_pool_size和large_pool_size部分,SGA_MAX_SIZE去除db_cache_size部分也被归入可变部分,所以很多时候我们看到的可变部分内存要远高于可变内存组件大小:
SQL> select
2 (select value from v$parameter where name='large_pool_size') + 3 (select value from v$parameter where name='shared_pool_size') + 4 (select value from v$parameter where name='java_pool_size') Vsize 5 from dual; VSIZE ---------- 134217728
Database Buffers指Buffer Cache的设置:
SQL> show parameter db_cache_size
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------ db_cache_size big integer 117440512
Redo Buffers指日志缓冲区分配的内存大小,这个参数值通常比log_buffers参数设置略大:
SQL> show parameter log_buffer
·29·
书名书名书名书名书名书名书名书名书名书名书名书名书名书名
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------ log_buffer integer 524288
这是因为Log Buffer并非按照数据块大小分配,在内存中通常需要设置保护页对Log Buffer进行保护。
当前SGA的分配和使用具体信息我们还可以通过V$SGASTAT视图查询得到。大家可能也会注意到,在V$SGASTAT中显示的Shared Pool大小和shared_pool_size设置的仍然不同,这是因为在共享池内存的分配和使用过程中会存在一定量的额外消耗,这部分内存在Oracle10g中被单独列出:
[oracle@danaly ~]$ sqlplus \
SQL*Plus: Release 10.2.0.1.0 - Production on Wed Apr 12 18:37:41 2006 Copyright (c) 1982, 2005, Oracle. All rights reserved. SQL> select * from v$sgainfo;
NAME BYTES RESIZEABLE -------------------------------- ---------- ---------- Fixed SGA Size 1222744 No Redo Buffers 7163904 No Buffer Cache Size 830472192 Yes Shared Pool Size 96468992 Yes Large Pool Size 4194304 Yes Java Pool Size 4194304 Yes Streams Pool Size 0 Yes Granule Size 4194304 No Maximum SGA Size 943718400 No Startup overhead in Shared Pool 46137344 No Free SGA Memory Available 0
此外,由于一些Bug的影响,可能v$sgastat视图显示的Shared pool会出现一些异常的情况,以下是曾经收到的一则异常报告。
数据库版本:
select * from v$version where rownum <2;
BANNER ---------------------------------------------------------------- Oracle9i Enterprise Edition Release 9.2.0.8.0 - Production
当前的Shared_pool_size设置为80M:
shared_pool_reserved_size integer 4194304 shared_pool_size integer 83886080
但是v$sgastat的显示出现了极度异常:
SELECT * ·30·