ID
NUMBER
缓冲池ID,和上面视图描述相同。
NAME
VARCHAR2(20)
缓冲池名称
BLOCK_SIZE
NUMBER
缓冲池块尺寸(字节为单位)
RESIZE_STATE
VARCHAR2(10)
缓冲池当前状态。
STATIC:没有被正在调 整大小
ALLOCATING:正在 分配内存给缓冲池(不能被用户取消)
ACTIVATING:正在 创建新的缓存块(不能被用户取消)
SHRINKING:正在删 除缓存块(能被用户取消)
CURRENT_SIZE
NUMBER
缓冲池大小(M为单位)
BUFFERS
NUMBER
当前缓存块数
TARGET_SIZE
NUMBER
如果正在调整缓冲池大小(即状态不为STATIC),这记录了调整后的大小(M为单位)。 如果状态为STATIC,这个值和当前大小值相同。
TARGET_BUFFERS
NUMBER
如果正在调整缓冲池大小(即状态不为STATIC),这记录了调整后的缓存块数。否则,这个值和当前缓存块数相同。
PREV_SIZE
NUMBER
前一次调整的缓冲池大小。如果从来没有调整 过,则为0。
PREV_BUFFERS
NUMBER
前一次调整的缓存块数。如果从来没有调整 过,则为0。
LO_BNUM
NUMBER
9i后已经废弃字段
HI_BNUM
NUMBER
9i后已经废弃字段
LO_SETID
NUMBER
9i后已经废弃字段
HI_SETID
NUMBER
9i后已经废弃字段
SET_COUNT
NUMBER
· v$buffer_pool_statistics
V$BUFFER_POOL_STATISTICS视图记录了所有缓冲池的统计数据。它的结构如下:
字段
数据类型
描述
ID
NUMBER
缓冲池ID,和上面视图描述相同。
NAME
VARCHAR2(20)
缓冲池名称
SET_MSIZE
NUMBER
缓冲池中缓存块的最大数
CNUM_REPL
NUMBER
在置换列表中的缓存块数
CNUM_WRITE
NUMBER
在写列表中的缓存块数
CNUM_SET
NUMBER
当前的缓存块数
BUF_GOT
NUMBER
读取过的缓存块数
SUM_WRITE
NUMBER
被写过的缓存块数
SUM_SCAN
NUMBER
被扫描过的缓存块数
FREE_BUFFER_WAIT
NUMBER
等待空闲块统计数
WRITE_COMPLETE_WAIT
NUMBER
等待完成写统计数
BUFFER_BUSY_WAIT
NUMBER
忙(正在被使用)等待统计数
FREE_BUFFER_INSPECTED
NUMBER
确认了的空闲缓存块数(即可用的)
DIRTY_BUFFERS_INSPECTED
NUMBER
确认了的脏缓存块数
DB_BLOCK_CHANGE
NUMBER
被修改过的数据块数
DB_BLOCK_GETS
NUMBER
读取过的数据块数
CONSISTENT_GETS
NUMBER
一致性读统计数
PHYSICAL_READS
NUMBER
物理读统计数
PHYSICAL_WRITES
NUMBER
物理写统计数
查看当前的Buffer Cache命中率:
SQL> select 1-(physical_reads)/(consistent_gets+db_block_gets)
2 from v$buffer_pool_statistics;
1-(PHYSICAL_READS)/(CONSISTENT
------------------------------
0.967658520581074
SQL>
· v$bh
这一视图在深入定位缓冲区问题时很有用。它记录 了缓冲区中所有数据块对象。粒度非常细。这个视图最初的目的是用于OPS(Oracle Parallel Server Oracle平行服务器,9i后称为RAC)的,是用于保证RAC中各个节点的数据一致性 的。但是,我们可以通过它来查询Buffer Cache的使用情况,找出大量消耗Buffer Cache的对象。下面的语 句就可以完成这一工作:
SQL> column c0 heading 'Owner' format a15
SQL> column c1 heading 'Object|Name' format a30
SQL> column c2 heading 'Number|of|Buffers' format 999,999
SQL> column c3 heading 'Percentage|ofData|Buffer' format 999,999,999
SQL> select
2 owner c0,
3 object_name c1,
4 count(1) c2,
5 (count(1)/(select count(*) from v$bh)) *100 c3
6 from
7 dba_objects o,
8 v$bh bh
9 where
10 o.object_id = bh.objd
11 and
12 o.owner not in ('SYS','SYSTEM')
13 group by
14 owner,
15 object_name
16 order by
17 count(1) desc
18 ;
C0 C1 C2 C3
--------------- ------------------------------ ---------- ----------
PLSQLDEV STANDARD_CITY 17290 72.5860621
DBOWNER MSG_LOG 2 0.00839630
DBOWNER COUNTRY_PK 1 0.00419815
DBOWNER PARAMETER 1 0.00419815
DBOWNER PARAMETER_PK 1 0.00419815
DBOWNER MSG_LOG_IDX1 1 0.00419815
6 rows selected
SQL>
更重要的是,这个视图记录的粒度非常细,一条记 录对应了一个数据块。这对于我们做内存问题分析或分析Oracle行为时很有帮助。
下面是这个视图的结构:
字段
数据类型
说明
FILE#
NUMBER
缓存块对应的数据块所在的数据文件号。可以 通过视图DBA_DATA_FILES或V$DBFILES查 询
BLOCK#
NUMBER
缓存块对应的数据块编号
CLASS#
NUMBER
分类编号
STATUS
VARCHAR2(1)
缓存块的状态
FREE:空闲,没有被使用
XCUR:排斥(正在被使用)
SCUR:可被共享
CR:一致性读
READ:正在从磁盘读入
MREC:处于从存储介质恢复状态
IREC:处于实例恢复状态
XNC
NUMBER
缓存块上由于和其他实例争用导致的PCM(Parallel Cache Management并行缓存管理)x to null锁的数 量。这一字段已经被废弃。
LOCK_ELEMENT_ADDR
RAW(4 | 8)
缓存块上PCM锁的地址。如果多个缓存块的PCM锁地址相同,说 明他们被同一锁锁住。
LOCK_ELEMENT_NAME
NUMBER
缓存块上PCM锁的地址。如果多个缓存块的PCM锁地址相同,说 明他们被同一锁锁住。
LOCK_ELEMENT_CLASS
NUMBER
缓存块上PCM锁的地址。如果多个缓存块的PCM锁地址相同,说 明他们被同一锁锁住。
FORCED_READS
NUMBER
由于其他实例的PCM锁锁住了该缓存块,导致当前实例尝试重新请求读该缓冲块的次数。
FORCED_WRITES
NUMBER
由于其他实例的PCM锁锁住了该缓存块,导致当前实例尝试重新请求写该缓冲块的次数。
DIRTY
VARCHAR2(1)
脏标志:Y – 块被修改过,是脏块;N – 不是脏块
TEMP
VARCHAR2(1)
是否为临时块:Y – 是;N – 否。
PING
VARCHAR2(1)
是否被ping住:Y – 是;N – 否。
STALE
VARCHAR2(1)
是否是陈旧块:Y – 是;N – 否。
DIRECT
VARCHAR2(1)
是否为直接读写块:Y – 是;N – 否。
NEW
VARCHAR2(1)
字段被废弃,始终为N
OBJD
NUMBER
数据块所属对象的对象标号,可以查询dba_objects
TS#
NUMBER
1.1.4. 共享池(Shared pool)
SGA中的共享池由库缓存(Library Cache)、字典缓存(Dictionary Cache)、用于并行执行消息的缓冲以及控制结构组成。
Shared Pool的大小由参数SHARED_POOL_SIZE决定。在32位系统 中,这个参数的默认值是8M,而64位系统 中的默认值位64M。最大为4G。
对于Shared Pool的内存管理,是通过修正过的LRU算法表来实现的。
下面分别介绍Shared Pool的几个组成部分。
1.1.4.1. 库缓存(Library Cache)
Library Cache中包括共享SQL区(Shared SQL Areas)、PL/SQL存储过程和包以及控制结构(如锁、库缓存句 柄)。
任何用户都可以访问共享SQL区(可以通过v$sqlarea访问,随后会介绍 这个重要视图)。因此库缓存存在于SGA的共享池中。
· 共享SQL区和私有SQL区
Oracle会为每一条SQL语 句运行(每运行一条语句Oracle都会打开一个游标)提供一个共享SQL区(Shared SQL Areas)和私有SQL区(Private SQL Areas属于PGA)。当发现两个(或多个)用户都在运行同一SQL语句时,Oracle会重新组织SQL区,使这些用户能重用共享SQL区。但他们还会在 私有SQL区中保存一份这条SQL语句的拷 贝。
一个共享SQL区 中保存了一条语句的解析树和查询计划。在多用户系统中,Oracle通过为SQL语句使用同一共享SQL区多次运行来节省内存。
当一条新的SQL语句被解析时,Oracle从共享池中分配一块内 存来存储共享SQL区。这块内存的大小与这条语句的复杂性相关。如果Shared Pool不够空间分配给共享SQL区,Oracle将 释放从LRU链表中查找到最近最少使用的内存块,直到有足够空间给新的语句的共享SQL区。如果Oracle释放的是一个共享SQL区的内存,那么相应的语句在下次执行时需要再次解析并重新分配共享SQL区。而从解析语句到分配共享SQL区是一个比较消 耗CPU的工程。这就是为什么我们提倡使用绑定变量的原因了。在没有使用绑定变量时,语句中的变量 的数值不同,oracle就视为一条新的语句(9i后 可以通过cursor_sharing来控制),重复上面的解析、内存分配的动作,将大大消耗系统 资源,降低系统性能。
· PL/SQL程 序单元
Oracle对于PL/SQL程 序单元(存储过程、函数、包、匿名PL/SQL块和触发器)的处理过程和对单个的SQL语句的处理过程相似。它会分配一个共享区来存储被解析、编译过的程序单元。同时分配一个私有区域来存放运 行程序单元的会话所指定的程序单元的参数值(包括本地变量、全局变量和包变量——这也叫做包的实例化)和用于执行程序所需的内存。如果多个用户运行同一个 程序单元,则他们共享同一个共享区域,并且各自保持一份私有区域,用于用户会话中指定的变量值。
而一个PL/SQL程 序单元中的每条单个SQL语句的处理过程则和上面描述的SQL语 句的处理过程相同。要注意一点,尽管这些语句是从PL/SQL程序单元中来的,但是Oracle还是会为这些语句分配一块共享SQL区,同 时为每个用户分配一个相应的私有SQL区。
数据块所在的表空间号,可以查询v$tablespaces
9i后已经废弃字段