1 mutex 等待
1 共享池内存结构
堆-区-chunk-子堆
共享池内存最上面是heap(堆),
在一个堆中,内存被划分为多个大小相关的区(extent),在区中又包含大小不相等的若干chunk,
chunk是共享池最基本的分配单元。
一个chunk也可以成为一个子堆,这个子堆内存被划分为若干大小相等的区,区中包含大小不等的chunk,而chunk又可以作为一个子子堆。。。。。
在上图中,最左边的是共享池的tio heap(顶层堆),右边是子堆,子堆之下还可以有子子堆,但通常情况下到子堆这一层,很少有子子堆出现。
2 共享池内存分配
进程需要在共享池分配内存存在两种模式
1 从top heap中分配(从顶堆中分配)
2 从某子堆中分配。
SQL> alter session set events 'immediate trace name heapdump level 2';
EXTENT 8 addr=000007FF03000000
Chunk 7ff03000060 sz= 48 R-stopper "reserved stoppe"
Chunk 7ff03000090 sz= 714576 R-perm "perm " alo=714576
Chunk 7ff030ae7e0 sz= 262184 R-perm "perm " alo=262184
Chunk 7ff030ee808 sz= 75720 R-free " "
Chunk 7ff03100fd0 sz= 48 R-stopper "reserved stoppe"
Chunk 7ff03101000 sz= 11938576 perm "perm " alo=11938576
Chunk 7ff03c63b10 sz= 3732488 perm "perm " alo=3732488
Chunk 7ff03ff2f18 sz= 80 freeable "allocate segmen"
Chunk 7ff03ff2f68 sz= 184 freeable "allocate segmen"
Chunk 7ff03ff3020 sz= 64 freeable "allocate segmen"
Chunk 7ff03ff3060 sz= 184 freeable "allocate segmen"
Chunk 7ff03ff3118 sz= 64 freeable "allocate segmen"
Chunk 7ff03ff3158 sz= 184 freeable "allocate segmen"
Chunk 7ff03ff3210 sz= 64 freeable "allocate segmen"
Chunk 7ff03ff3250 sz= 184 freeable "allocate segmen"
Chunk 7ff03ff3308 sz= 64 freeable "allocate segmen"
Chunk 7ff03ff3348 sz= 184 freeable "allocate segmen"
Chunk 7ff03ff3400 sz= 64 freeable "allocate segmen"
Chunk 7ff03ff3440 sz= 184 freeable "allocate segmen"
Chunk 7ff03ff34f8 sz= 64 freeable "allocate segmen"
Chunk 7ff03ff3538 sz= 184 freeable "allocate segmen"
Chunk 7ff03ff35f0 sz= 64 freeable "allocate segmen"
Chunk 7ff03ff3630 sz= 184 freeable "allocate segmen"
Chunk 7ff03ff36e8 sz= 64 freeable "allocate segmen"
Chunk 7ff03ff3728 sz= 184 freeable "allocate segmen"
Chunk 7ff03ff37e0 sz= 64 freeable "allocate segmen"
Chunk 7ff03ff3820 sz= 184 freeable "allocate segmen"
Chunk 7ff03ff38d8 sz= 64 freeable "allocate segmen"
Chunk 7ff03ff3918 sz= 184 freeable "allocate segmen"
Chunk 7ff03ff39d0 sz= 64 freeable "allocate segmen"
Chunk 7ff03ff3a10 sz= 184 freeable "allocate segmen"
Chunk 7ff03ff3ac8 sz= 64 freeable "allocate segmen"
Chunk 7ff03ff3b08 sz= 184 freeable "allocate segmen"
Chunk 7ff03ff3bc0 sz= 64 freeable "allocate segmen"
Chunk 7ff03ff3c00 sz= 184 freeable "allocate segmen"
Chunk 7ff03ff3cb8 sz= 64 freeable "allocate segmen"
Chunk 7ff03ff3cf8 sz= 184 freeable "allocate segmen"
Chunk 7ff03ff3db0 sz= 64 freeable "allocate segmen"
Chunk 7ff03ff3df0 sz= 184 freeable "allocate segmen"
Chunk 7ff03ff3ea8 sz= 184 freeable "allocate segmen"
Chunk 7ff03ff3f60 sz= 16480 freeable "IMC extent map " ds=000007FF00D6F018
Chunk 7ff03ff7fc0 sz= 16424 freeable "ktsj_init_sga p"
Chunk 7ff03ffbfe8 sz= 16408 freeable "ktilm hash tabl"
EXTENT 9 addr=000007FF04000000
3 chunk类型
在oracle中有一个X$视图,X$KSMSP专门记录共享池中堆所有chunk的情况。它有多少行代表共享池中包含多少个chunk,ksmchsiz列代表每个chunk的大小。
SQL> desc x$ksmsp
名称 是否为空? 类型
----------------------------------------- -------- --------------------
ADDR RAW(8)
INDX NUMBER
INST_ID NUMBER
CON_ID NUMBER
KSMCHIDX NUMBER
KSMCHDUR NUMBER
KSMCHCOM VARCHAR2(16)
KSMCHPTR RAW(8)
KSMCHSIZ NUMBER
KSMCHCLS VARCHAR2(8)
KSMCHTYP NUMBER
KSMCHPAR RAW(8)
SQL>
SQL> select count(1),round(sum(ksmchsiz/1024/1024)) from x$ksmsp;
在视图中存在ksmchcls记录chunk的类型
SQL> select distinct ksmchcls from x$ksmsp order by ksmchcls;
KSMCHCLS
--------
R-free
R-freea
R-perm
R-recr
free
freeabl
perm
recr
已选择 8 行。
SQL> select ksmchcls ,count(1),round(sum(ksmchsiz/1024/1024)) from x$ksmsp group
by ksmchcls order by ksmchcls;
KSMCHCLS COUNT(1) ROUND(SUM(KSMCHSIZ/1024/1024))
-------- ---------- ------------------------------
R-free 40 4
R-freea 92 1
R-perm 18 11
R-recr 5 0
free 1549 10
freeabl 7549 14
perm 265 250
recr 5897 14
其中R表示保留池中的类型。
free:空闲的chunk,所有的free chunk都会被链入freelist链表中。
perm:永久的chunk,和free对应这种chunk不会被释放,在数据库运行期间一直保存,oracle中众多的内存结构以及X$类型的视图占用的内存区域,
recr::可以重建的chunk。
freeabl:可空闲,可覆盖,可释放。
常用语sql,sql的执行计划等信息就是可释放,可重建的,如果共享池内存紧张了,某些sql会被“老化”,其实就是sql所占用的内存会被释放、覆盖。当老化的sql再次执行时,它的信息将在共享池被重建。
4 chunk与LRU链表的关系
在buffer cache中所有的数据块都会在LRU链表中,而共享池不是,
只有recr类型的chunk才会被链接在LRU链表中。
只有free类型的chunk才会被链接早freelist链表中。
5 sql的内存结构,父游标,子游标
共享池的主要租用之一就是保存sql语句的相关信息,如依赖性,执行计划等信息。
select *from t1 where id=99;
问题1 如何确定sql语句位置?
在buffer cache中根据数据文件号和块号做hash运算计算到哪条hash chain,检索bh进行查询。
而在共享池中则是一条sql语句文件作hash运算。
在hash表的bucket中,存放着一个链表,它会将suoyou游标的句柄连接在一起。
问题2 为什么要用父子游标?
避免hash链表过长导致检索时间变长。
oracle算法规定必须一父一子,很多情况下都是一父多子情况,也就是说每个游标oracle都会设定它的父游标,如果sql文本相同但是无法共享执行计划就会出现一个父多个子
6 sql内存结构之2 父游标句柄
共享池中的句柄类似于buffe cache中的bh。用于保存锁和状态等信息。
bh中记录buffer是否为脏,它所在的链表位置以及buffer pin状态等信息。
父游标句柄对应独立的chunk,其类型为recr,它的地址可以在视图X$KGLOB中查询
select kglhdadr,kglnaobj from x$kglob where kglnaobj like '%select%'
and kglhdadr=kglhdpdr;
如下;
7 sql所占用的内存
根据上述的sql机构图,上述sql语句占用9个chunk。
v$sql.sharable_mem, v$sqlarea.sharable_mem,而v$sql来自于x$KGLCURSOR_CHILD,V$SQLAREA来源于X$KGLCURSOR_CURSOR_SQLID
8 ORA--4031解析
1 共享池内存过小,
2 对象太多。
3 碎片过大。