shared pool 深入分析!

1.shared pool:

SQL> show sga;

Total System Global Area  849530880 bytes
Fixed Size                  1339824 bytes   --固定区域
Variable Size             549457488 bytes   --可变区域
Database Buffers          293601280 bytes
Redo Buffers                5132288 bytes
除ShowSga外,我们还可以用V$sgastat视图显示SGA各内存结构的大小
SQL> select * from v$sgastat where rownum < 11;

POOL         NAME                                BYTES
------------ ------------------------------ ----------
             fixed_sga                         1339824
             buffer_cache                    293601280
             log_buffer                        5132288
shared pool  dpslut_kfdsg                          256
shared pool  hot latch diagnostics                  80
shared pool  kkj jobq  wor                        4104
shared pool  vips_package_file                     924
shared pool  ENQUEUE STATS                       16296
shared pool  sskgplib                             1052
shared pool  transaction                        426316

已选择10行。

在一个很高的层次上来看,shared pool可以分为库缓存(library cache)和数据字典缓存(dictionary cache)。Library cache存放了最近执行的SQL语句、存储过程、函数、解析树以及执行计划等。dictionary cache则存放了在执行SQL语句过程中,所参照的数据字典的信息,包括SQL语句所涉及的表名、表的列、权限信息等。dictionary cache也叫做row cache,因为这里面的信息都是以数据行的形式存放的,而不是以数据块的形式存放的。


oracle对SQL语句进行了概括和抽象,将SQL语句提炼为两部分,一部分是SQL语句的静态部分,也就是SQL语句本身的关键词、所涉及的表名称以及表的列等。另一部分就是SQL语句的动态部分,也就是SQL语句中的值(即表里的数据)。


从上面这个图中可以看到,当SQL语句进入library cache时,oracle会到dictionary cache中去找与sharedpool_test表有关的数据字典信息,比如表名、表的列等,以及用户权限等信息。如果发现dictionary cache中没有这些信息,则会将system表空间里的数据字典信息调入buffer cache内存,读取内存数据块里的数据字典内容,然后将这些读取出来的数据字典内容按照行的形式放入dictionary cache里,从而构造出dc_tables之类的对象。然后,再从dictionary cache中的行数据中取出有关的列信息放入library cache中。

从一个物理的层面来看,shared pool是由许多内存块组成,这些内存块通常称为chunk.Chunk是shared pool中内存分配的最小单位,一个chunk中的所有内存都是连续的。这些chunk可以分为四类,这四类可以从x$ksmsp(该视图中的每个行都表示shared pool里的一个chunk)的ksmchcls字段看到:

1) free:(即马上使用)这种类型的chunk不包含有效的对象,可以不受限制的被分配。
2) recr:意味着recreatable(可再性),这种类型的chunks里包含的对象可以在需要的时候被临时移走,并且在需要的时候重新创建。比如对于很多有关共享SQL语句的chunks就是recreatable的。
3) freeabl:这种类型的chunks包含的对象都是曾经被session使用过的,并且随后会被完全或部分释放的。这种类型的chunks不能临时从内存移走,因为它们是在处理过程中间产生的,如果移走的话就无法被重建。

4) perm:意味着permanent(永久、不可再生),这种类型的chunks包含永久的对象,大型的permanent类型的chunks也可能含有可用空间,这部分可用空间可以在需要的时候释放回shared pool里。

在shared pool里,可用的chunk(free类型)会被串起来成为可用链表(free lists)或者也可以叫做buckets(一个可用链表也就是一个bucket)。我们可以使用下面的命令将shared pool的内容转储出来看看这些bucket.

SQL> alter session set events 'immediate trace name heapdump level 2';

会话已更改。

select d.value || '/' || lower(rtrim(i.instance, chr(0))) || '_ora_' ||
  2         p.spid || '.trc' trace_file_name
  3    from (select p.spid
  4            from sys.v$mystat m, sys.v$session s, sys.v$process p
  5           where m.statistic# = 1
  6             and s.sid = m.sid
  7             and p.addr = s.paddr) p,
  8         (select t.instance
  9            from sys.v$thread t, sys.v$parameter v
 10           where v.name = 'thread'
 11             and (v.value = 0 or t.thread# = to_number(v.value))) i,
 12         (select value from sys.v$parameter where name = 'user_dump_dest') d;

TRACE_FILE_NAME
---------------------------------------------------------------------------------------------------
/u01/app/diag/rdbms/orcl/orcl/trace/orcl_ora_3844.trc
然后打开产生的转储文件,找到“FREE LISTS”部分:
FREE LISTS:
 Bucket 0 size=16
 Bucket 1 size=20
 Bucket 2 size=24
  Chunk 51ffffe8 sz=       24    free      "               "
 Bucket 3 size=28
 Bucket 4 size=32
 Bucket 5 size=36
 Bucket 6 size=40
 Bucket 7 size=44
 Bucket 8 size=48
 Bucket 9 size=52
 Bucket 10 size=56
 Bucket 11 size=60
 Bucket 12 size=64
 Bucket 13 size=68
 Bucket 14 size=72
 Bucket 15 size=76
 Bucket 16 size=80
 Bucket 17 size=84
 Bucket 18 size=88
 Bucket 19 size=92
  Chunk 523fffa4 sz=       92    free      "               "
 Bucket 20 size=96
 Bucket 21 size=100
... ...

通过如下语句可以看见数据库中的shared pool数量:

SQL> select count(*) from v$latch_children where name = 'shared pool';

  COUNT(*)
----------
         7
在shared pool上面的等待事件就是:
SQL> select name,parameter1,parameter2,parameter3 from v$event_name where name like 'latch: shared pool';

NAME                           PARAMETER1           PARAMETER2           PARAMETER3
------------------------------ -------------------- -------------------- --------------------
latch: shared pool             address              number               tries


2.library cache:


library cache就是使用多个hash bucket来管理的。每个hash bucket后面都串连着多个句柄(该句柄叫做library cache object handle),这些句柄描述了library cache里的对象的一些属性,包括名称、标记、指向对象所处的内存地址的指针等。

当一条SQL语句进入library cache的时候,先将SQL文本转化为对应ASCII数值,然后对该这些ASCII数值进行hash函数的运算,传入函数的是SQL语句的名称(name,对于SQL语句来说其name就是SQL语句的文本)以及命名空间(namespace,对于SQL语句来说是“SQL AREA”,表示共享游标。可以从视图v$librarycache里找到所有的namespace)。运用hash函数后得到一个值,该值就是hash bucket的号码,从而该SQL语句被分配到该号的hash bucket里去。实际上,hash bucket就是通过串连起来的对象句柄才体现出来的,它本身是一个逻辑上的概念,是一个逻辑组,而不像对象是一个具体的实体。

当某个进程需要处理某个对象时,比如处理一条新进入的SQL语句时,它会对该SQL语句应用hash函数算法,以决定其所在的hash bucket的编号,然后进入该hash bucket进行扫描并比较。有可能会发生该对象的句柄存在,但是句柄所指向的对象已经被交换出内存的情况出现。这时对应的对象必须被再次装载(reload)。也可能该对象的句柄都不存在,这时进程必须重新构建一个对象句柄挂到hash bucket上,然后再重新装载对象。SQL语句相关的对象有很多(最直观的就是SQL语句的文本),这些对象都存放在library cache里,它们都通过句柄来访问。可以把library cache理解为一本书,而SQL语句的对象就是书中的页,而句柄就是目录,通过目录可以快速定位到指定内容的页。

对象句柄存放了对象的名称(name)、对象所属的命名空间(namespace)、有关对象的一些标记(比如对象是否为只读、为本地对象还是远程对象、是否被pin在内存中等等)以及有关对象的一些统计信息等。而且,对象句柄中还存放了当前正在lock住和pin住该对象的用户列表、以及当前正在等待 lock和pin该对象的用户列表。对象句柄中存放的最重要的内容就是指向Heap 0对象的指针了。Heap 0用来存放与对象有直接关系的一些信息,比如对象类型、对象相关的表(比如依赖表、子表等)、指向对象的其他数据块的指针(这些数据块指向了实际存放 SQL文本、PL/SQL代码、错误信息等的大内存块,这些大内存块依次叫做Heap 1、2、3、4等)等信息。

Heap是通过调用服务器进程进行分配的,任何对象都具有heap 0,至于还应该分配哪些其他的heap则是由对象的类型决定的,比如SQL游标具有heap 1和 6,而PL/SQL程序包则具有heap 1、2、3和4.按照heap的使用情况,oracle会在SGA(library cache)、PGA或UGA中分配heap,但是heap 0始终都是在library cache中进行分配的。如果所请求的heap已经在SGA中分配了,则不会在PGA中再次分配heap.Heap是由一个或多个chunk组成的,这些 chunk可以是分散的分布在library cache中的,不需要连续分布。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
To implement a shared resource pool in C++, you can modify the previous example by introducing shared ownership of resources using smart pointers. Here's an updated version: ```cpp #include <iostream> #include <queue> #include <mutex> #include <condition_variable> #include <memory> template<typename T> class ResourcePool { public: ResourcePool(size_t maxSize) : max_size(maxSize), available_resources(0) {} std::shared_ptr<T> acquire() { std::unique_lock<std::mutex> lock(mutex); while (resources.empty()) { if (available_resources >= max_size) { // Wait until a resource is released cv.wait(lock); } else { // Create a new resource if the pool is not full resources.push(createResource()); ++available_resources; } } std::shared_ptr<T> resource = resources.front(); resources.pop(); return resource; } void release(std::shared_ptr<T> resource) { std::lock_guard<std::mutex> lock(mutex); resources.push(resource); cv.notify_one(); } private: size_t max_size; size_t available_resources; std::queue<std::shared_ptr<T>> resources; std::mutex mutex; std::condition_variable cv; // Create a new resource object (replace with your own code) std::shared_ptr<T> createResource() { return std::make_shared<T>(); } }; // Example usage class MyResource { public: void use() { std::cout << "Using resource" << std::endl; } }; int main() { ResourcePool<MyResource> pool(5); // Acquire and use resources for (int i = 0; i < 10; ++i) { std::shared_ptr<MyResource> resource = pool.acquire(); resource->use(); pool.release(resource); } return 0; } ``` In this updated example, the `ResourcePool` class now uses `std::shared_ptr` to manage shared ownership of resources. When acquiring a resource, a `std::shared_ptr` is returned instead of a raw pointer. This allows multiple threads or parts of the code to safely share and use the resource without worrying about premature destruction. When releasing a resource, a `std::shared_ptr` is passed back to the pool instead of a raw pointer. Note that the `createResource` function now uses `std::make_shared` to create the resource object, which ensures that the object is properly managed by a shared pointer. By using shared pointers, you can safely share and manage resources within the resource pool, allowing multiple parts of your code to use them without concerns about memory ownership and deallocation.

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值