介绍free lists及shared pool lru list.
Shared pool中chunk的分配
1、shared pool中的chunk的大小是不一样的,但是是连续的
2、因为chunk是分配的最小单元,因此session需要给对象分配空间的时候,会以chunk为单位进行申请
3、可用的chunk(free)会形成一个链表 feee lists,便于进行分配的时候,可以通过遍历链表寻找到可用的适合的chunk,链表是chunk进行组织和管理的一种方式
4、一个可用的chunk链表是一个bucket,shared pool中会有很多的bucket,不同的bucket中的chunk的大小不同,一般是随着bucket编号的增加而增长的
5.当需要从shared pool中寻找chunk的时候,首先会定位一个bucket,然后遍历bucket,寻找最合适的chunk, 如果chunk的空间比需要的空间大,那么这个chunk就拆分成两个,一个被分配、一个成为free,重新挂接到相应大小的bucket上。
6、在寻找chunk的过程中,如果一个bucket中没有合适的chunk,接着寻找另外一个非空的bucket,如果所有的bucket中都没有合适的chunk,那么就从rec类型的链表中释放一部分的空间,为free,或将free做适当合并 。。注意:只有rec类型的chunk能够被释放空间,即使释放了空间,这些空间可能都不是连续的,都是一些很小的chunk,这样可能形成这样一种情况,shared pool中有空间但是是大量的非常小的chunk,这样在寻找chunk的时候,也很难寻找到合适的chunk--共享池碎片
7、shared pool中所有类型的chunk都是以链表的方式进行管理的
##############
free list 空闲列表
按bucket划分,共有255个,bucket 0---bucket 254
每个bucket上挂有一个 chunk list;
free lists上的都是未使用的chunk--状态free
free lists上Bucket大小的分布情况: --环境LINUX 32位/ORACLE 11.2.0.4
Bucket 0-199之前 Bucket size以4bytes递增
Bucket 200-239这一段的Bucket size以64bytes递增
Bucket 240--254的Bucket size增长看起来没太大规律,总之是递增了哈哈。
因为free chunk数量非常的多,这样划分每个Bucket容纳的chunk数量减少,查找效率提高,对shared pool latch的争用也大大减少。注意:如果在shared pool中出现了大量的小的free chunk,就会出现share pool latch争用的情况,即使增加共享池的大小,这个问题随着时间还是会出现的。
RESERVED FREE LISTS:
RESERVED FREE LISTS上的bucket个数我DUMP出来的是15个。
保留FREE LISTS,在SQL语句所需CHUNK大于4400bytes时,会在RESERVED FREE LISTS中查找空闲CHUNK。
如果SQL语句所需CHUNK不大于4400bytes时,只会在free list 中查找CHUNK。
这个是由隐含参数控制的:_shared_pool_reserved_min_alloc minimum allocation size in bytes for reserved area ,默认值4400
###################
DUMP 共享池查看free lists/bucket/RESERVED FREE LISTS结构:--用新建会话来做
alter session set events 'immediate trace name heapdump level 2';
select value from v$diag_info where name like 'De%';
/u01/diag/rdbms/bys3/bys3/trace/bys3_ora_7876.trc
查看TRACE文件内容: --找这一段的方法:VI搜索HEAP DUMP
Chunk 2bffa844 sz= 22460 freeable "character set m"
Total heap size =146798680 -- 146798680/1024/1024 --139.99813 初始化参数:shared_pool_size--140M
FREE LISTS: ------空闲列,可以明显看出bucket大小分配的规律--从小到大,共有255个buckets,从16bytes到64k,采用此方法分配内存,可以有效的减少内存碎片。每个Bucket之间都用double linked 相互连接
Bucket 0 size=
16
Chunk 2bc00048 sz= 0 kghdsx
Bucket 1 size=20 20字节的Bucket 1,有很多个Chunk,节约篇幅省略了
Chunk 23a60468 sz=
20 free " "
Chunk的地址、大小、状态
Chunk 23ceb498 sz= 20 free " "
Chunk 237fcde4 sz= 20 free " "
Bucket 2 size=24 --Bucket 2
--24字节,也就是Bucket 2的 size范围在20-24字节。。
Chunk 245b13e4
sz= 24 free " "
Chunk 23ace7c0 sz= 24 free " "
Chunk 239c5a28 sz= 24 free " "
Bucket 3 size=28
Chunk 24540e9c
sz= 28 free " "
Chunk 2521209c sz= 28 free " "
Chunk 23483448 sz= 28 free " "
………………
Bucket 198 size=1388
Bucket 199 size=1452
---------- Bucket 200之前 Bucket size以4bytes递增
Chunk 2347d2ac sz= 1492 free " "
Bucket 200 size=1516
----------Bucket 200之后 Bucket size以64bytes递增
Chunk 24b28a94 sz= 1548 free " "
Bucket 201 size=1580
Chunk 2433bb14 sz= 1620 free " "
Chunk 2463a89c sz= 1620 free " "
Chunk 24b829c4 sz= 1620 free " "
Bucket 202 size=1644
Chunk 23498518 sz= 1704 free " "
Chunk 23de90d0 sz= 1696 free " "
………………
Bucket 236 size=3820
Bucket 237 size=3884
Bucket 238 size=3948
Bucket 239 size=4012 --------------Bucket 200到-Bucket 239这一段的Bucket size以64bytes递增
Bucket 240 size=4096 -----------Bucket 239之后 的Bucket size增长看起来没太大规律,总之是递增了哈哈
Bucket 241 size=4100
Bucket 242 size=4108
Bucket 243 size=8204
Bucket 244 size=8460
Bucket 245 size=8464
Bucket 246 size=8468
Bucket 247 size=8472
Bucket 248 size=9296
Bucket 249 size=9300
Bucket 250 size=12320
Bucket 251 size=12324
Bucket 252 size=16396
Bucket 253 size=32780
Bucket 254 size=65548
Total free space = 518232
RESERVED FREE LISTS: --保留FREE LISTS,解析方法同上。保留池中CHUNK都比较大
Reserved bucket 0 size=16
Chunk 23420320 sz= 676 R-free " "
Chunk 23427b94 sz= 3420 R-free " "
Chunk 2342618c sz= 952 R-free " "
Chunk 23800050 sz= 1040 R-free " "
Chunk 23400050 sz= 2824 R-free " "
Chunk 25bff028 sz= 4032 R-free " "
Chunk 293ff788 sz= 2144 R-free " "
Reserved bucket 1 size=4400 --这个如果用的会,4564-4400,剩下164字节会成为新CHUNK
Chunk 23430a40 sz= 4564 R-free " "
Reserved bucket 2 size=8204
Reserved bucket 3 size=8460
Reserved bucket 4 size=8464
Reserved bucket 5 size=8468
Reserved bucket 6 size=8472
Chunk 2342b988 sz= 9136 R-free " "
Reserved bucket 7 size=9296
Reserved bucket 8 size=9300
Reserved bucket 9 size=12320
Reserved bucket 10 size=12324
Reserved bucket 11 size=16396
Chunk 234161f8 sz= 16448 R-free " "
Reserved bucket 12 size=32780
Reserved bucket 13 size=65548
Chunk 23401d50 sz= 72296 R-free " "
Chunk 23815668 sz= 125312 R-free " "
Chunk 23c00050 sz= 180380 R-free " "
Reserved bucket 14 size=1990652
Total reserved free space = 6712468 --总空闲保留空间是6.4M,shared_pool_reserved_size 初始化参数大小是 7M,用了0.6M
######################
shared pool LRU链
shared pool LRU链上挂的都是recreate、freeabl状态的chunk,一个SQL语句可能需要多个CHUNK,在LRU链上找到recreate状态的chunk,然后在
recreate状态的chunk下再下挂freeabl状态的CHUNK,--避免全部CHUNK在LRU链上导致LRU链太长。
TRACE文件中找到关于(lru first)的一段,方法同上:
Reserved bucket 14 size=1990652
Total reserved free space = 6712468
UNPINNED RECREATABLE CHUNKS (lru first):
Chunk 246c9848 sz= 348 recreate "KGLHD " latch=(nil) --
latch状态为空,
Chunk SIZE是348字节,状态
recreate,
Chunk 237cb10c sz= 4096 recreate "KGLH0^b9197c6e " latch=(nil)
Chunk 24bb5df0 sz= 364 recreate "KGLHD " latch=(nil)
Chunk 241aa1b8 sz= 4096 recreate "KGLH0^59449e50 " latch=(nil)
Chunk 252640a0 sz= 364 recreate "KGLHD " latch=(nil)
Chunk 23a619a0 sz= 4096 recreate "KGLH0^d5f1e0d7 " latch=(nil)
Chunk 23465600 sz= 348 recreate "KGLHD " latch=(nil)
Chunk 2346575c sz= 1036 recreate "KGLHD " latch=(nil)
Chunk 23465b68 sz= 4096 recreate "KGLH0^c6e0d102 " latch=(nil)
--一个recreate状态CHUNK下的多个freeable状态CHUNK
ds 24bdecb0 sz= 4096 ct= 1
Chunk 23466b68 sz= 4096 freeable "SQLA^1536bb77 " ds=0x23db5bd8
Chunk 23467b68 sz= 144 freeable "KGLDA "
Chunk 23467bf8 sz= 4096 freeable