oracle sga 之 shared pool

oracle sga 之 shared pool


原文链接:ORACLE SGA之shared pool

shared pool 的内存块组成

shared pool中主要的内存区域:freelibrary cacherow cache

为了确保共享池中共享数据的访问性能,共享池的每次内存分配都必须是连续的内存空间,经过一段时间的运行,共享池中会产生一些碎片,这些碎片分布在一些连续分配的空间之间。

共享池堆的内部结构

oracle 的内存空间分配是采用堆管理(HEAP)的模式。比如 SGA HEAPPGA HEAPHEAP TABLE 等都是堆内存管理。每个堆包含一个堆句柄和一系列的内存扩展,每个扩展又包含一系列连续的chunk。内存申请者通过在堆上申请空间的模式来获得内存。

堆创建包含两个步骤
  • 一是初始化堆的句柄
  • 二是给堆分配空间
chunk 中分配空间的基本顺序如下

1).首先搜索 freelist 上是否存在可以释放的 chunk (在该区域查找的时候首先根据需要分配空间的大小,找到相应的 bucket ,然后搜索整个链表,如果找到了大小相同的 chunk ,那么就直接分配使用。如果找不到合适的chunk,就会选择一个稍大的chunk,分配一个和所需空间大小一致的chunk,剩下的空间根据大小挂载到相应的bucket链表上)。

2).如果没找到,就查找是否有 recreateablechunk 可以释放。释放已经使用的 chunk,需要用到 LRU 链表。LRU 链表根据使用的频繁程度,通过一个双向链来串联已经被分配的chunk。如果在 LRU 链上找到了可以释放的 chunk ,就通知 HEAP MANAGER 去释放,如果该 chunk 是被锁住的,首先要解锁,然后才能释放。HEAP MANAGER 在释放内存时,会自动合并碎片。

3).如果此时还没有找到可以释放的 chunk,就从父堆里分配空闲的空间。

4).如果父堆无法分配空间,就会报错。

free空间

是一个一个的内存块,使用链(chain)将空闲内存块链起来,(每个链上所挂载的内存块大小是不一样的)。如:硬解析一个 sql 语句,需要根据解析的sql语句和sql语句的执行计划,它所需要占用的实际内存空间,从相应的链上找空间存放。硬解析需要内存空间,根据实际大小的 free 内存空间中的链中找到相应大小内存块使用,会产生小内存块(内存碎片)。系统如果有大量硬解析的话。虽然 free 里面还有很多空间,但是所有的空间都是小的。并不能使用。

SQL>select * from v$sgastat where pool='shared pool' and name='free memory';

library cache空间

library cache 里面有很多链,链下挂有很多 chunk,但是 chunk 里面都写了内容(sql,sql执行计划)。

根据什么把不同的chunk写上内存后挂在不同链上

sql语句所有的字母转换成 ASCII 码值,就成了数字,对这些数字经过几次运算,就是链的编号,这个 sql 语句就挂到所对应的编号上。当再次执行sql 语句的时候,就会从对应编号的链上去找对应的 chunk

SQL>select * from v$sgastat where name='library cache';

数据字典缓存(row cache)

数据字典缓存不是纯粹的数据字典表的缓存,数据字典缓存是经过组织的,用于数据库运行中 sql 解析、权限控制等用途的内部数据结构,是一种字典表的内存视图。如:在执行某个 sql 的时候,为了 sql 解析,需要访问一些字典表,从中获取一些数据,那么它会通过一些递归调用 sql 来完成这些事情。首先需要将数据块从系统表空间中读取到 DB cache ,然后从 DB cache 中获得 sql 所需要的行数据。为了减少递归 sql 的执行开销,这些行数据被缓存在共享池中,这个缓存就是数据字典缓存。

SQL>select * from v$sgastat where name='row cache';

执行一条之前为缓存的sql语句,查看链表中chunk数量的变化

SQL>select count(*) from x$ksmsp;

COUNT(*)
36635

SQL> select count(*) from dba_indexes;
–第一次执行发生硬解析,链上的 chunk 数量将有所增加

COUNT(*)
2344

SQL> select count(*) from x$ksmsp;

COUNT(*)
36650

SQL> alter system flush shared_pool;
–将 shared pool 清空,之后第一次执行的所有 DML 语句都将是硬解析

shared pool 中的保留池设置

如果共享池中碎片化变得十分严重,就会导致比较大的共享内存分配无法满足需求,oracle在共享池中设计了保留池.
保留池的设计目的是为了在共享池碎片化很严重的时候,还能够有一部分保留空间,用于较大的内存分配。可以通过参数shared_pool_reserved_size来设置保留池的大小(由于 oracle 的内存自动管理机制,一般情况下不需要手动设置)。
SQL> show parameter shared_pool_reserved_size;
NAME TYPE VALUE


shared_pool_reserved_size big integer 6081740

保留池的使用条件
  1. 必须是在共享池的 freelist 中找不到足够大的 chunk
  2. 分配的内存容量要大于 shared_pool_reserved_min_alloc 的设定值(从8i开始该参数变为隐含参数,即shared_pool_reserved_min_alloc,默认值为4400B),只有大于该设定值的内存分配才被认为是大内存分配

原文链接:ORACLE SGA之shared pool

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值