注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

饥民2011

一直在搬砖

 
 
 

日志

 
 
 
 

Shared pool内存块组成结构及4031错误原因分析  

2013-01-18 20:21:55|  分类: Oracle |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
这篇文章是参考甲骨论老相老师的教学视频所做的学习笔记:
http://v.youku.com/v_show/id_XMzkyMDQ4MzUy.html

之前提到Shared pool的作用:
Shared pool是用来缓存sql语句以及sql的执行计划的,

而share pool包含3主要大部分(还有其他很多部分)
分别是library cache, rowcache和 free memory
Shared pool内存块组成结构及4031错误原因分析 - 饥民 - 饥民2011
 

首先强调一句: 我们可以手动设置Shared pool的大小, 但是并不能制定shared pool里面 Free/Library Cache/rowcache 等各部分的大小的.
1.现在分析下Free 空间的内存空间:
其实可以参考下图:
Shared pool内存块组成结构及4031错误原因分析 - 饥民 - 饥民2011
 
 
       如上图,  其实Free空间并不是1个大的内存块, 而是由许多个有固定顺序内存链(chain)组成的,其中每1条chain都有起始位置和终点,在每1条chain上都挂着许多大小相近的内存块(chunk).例如上面第一条chain挂着chunk大小大概是每个4k,中间是每个chunk 8k,最下面果条每个12k啦~

        但是了解过数据结构的都知道, 内存链chain在物理上是不存在的, 而每个chunk也不是物理上相邻的, 每1条链实际上是分别在内存里各个位置的若干个chunk组成. 第1个chunk的头部放着这条chain的起始位置,也就是这条chain的内存位置,然后尾部放着1个指针,指向下1个chunk的内存地址..  直到之后1个chunk尾部不放指针. 这样就组成了1条内存链chunk

但是逻辑上可以参照上图理解啦~

2. 现在要解析一条sql语句, 需要占用free空间.
   假如,现在要解析一条新的语句, 需要额外的10k空间,  那么server process会怎么找出这10k的空间呢,

如下图, 首先下图中8k那第条链,它的chunk都是8k - 12k的, 所以server process会找这一条链遍历,假如它找到一个chunk是11k了,那么它会将这个chunk分成10k 和 1k两个部分,  其中10k 那个部分作为1个新的chunk放到 属于library cache的chain中, 就相当于把这个chunk从free空间移到 library cache了(当然不是物理上移动这个chunk,只需修改相应的chunk尾部指针).  而剩余的1k那个部分,也不能留在8k这一条链了, 会比移到存放1k左右chunk的那条链.
Shared pool内存块组成结构及4031错误原因分析 - 饥民 - 饥民2011
 
 由这过程可以得出,这种sql语句解析动作很可能会产生一些小的内存碎片(1k那个部分), 实际上这种sql动作就是所谓的硬解析,而软解析只需在library cache查找出缓存的执行计划,是不需要去征用Free memory的.

关于硬解析和软解析可以参考:http://nvd11.blog.163.com/blog/static/200018312201301682642475/

3. 4031错误的产生

      所以说硬解析会产生内存碎片, 而一个服务器在进行大量的硬解析是则在shared pool产生大量的碎片, 这时即使Free Memory空间内还有不少的空间, 但里面很可能都是小chunk(碎片), 而没有大的chunk了.

       这时,若数据库又接受到1个很复杂的sql语句要进行硬解析, 需要在free空间找一些大的chunk,但是free空间内只有碎片..这样这个硬解析会失败,而oracle则可能会报1这种很经典的错误,就是4031错误.

所以4031错误的产生原因有两个:

1. 数据库大量的硬解析.
2. 大量硬解析产生大量的碎片,而这时又要执行1个复杂的硬解析动作.


4. 内存链(chain)的结构.
其实内存链的结构可以参考下图啦:
Shared pool内存块组成结构及4031错误原因分析 - 饥民 - 饥民2011
 
上图是由3个chunk组成的内存链 chain.

可以看出内存chain内的chunk在物理上并不一定是相邻的,而且也不一定是在物理上按顺序排列的.
如上图, 物理上排中间那个chunk才是chain中的第一个chunk, 因为没有指针指向它的头部地址, 然后它的尾部指向第2个chain..

而第3个chain因为他的尾部是空指针,所以他是这个内存链的最后1个chunk.

所以当加入和删除chunk时只需改变相应chunk的指针指向就可以了
其实这是1个经典的链表结构啦.

5. 内存链(chain)的一些特性

所以chain有两个特点:
1. 由多个chunk串联组成.
2. 可以遍历(根据指针去遍历啦)

而Oracle 会 让一种叫Latch的锁去保护chain的结构.


6. Server process会写一些什么内容进入Chunk呢.

我们由上面的图解可知. 那些chunk在free空间里面是空的, 搬到library cache里面会被写上内容了.
下面就分析到底写了什么数据进去..

我们知道library cache是用来存放sql语句和其执行计划的, 那么里面数据肯定与之相关了:

首先
sql语句会被转换成ASCII码, 然后经过一系列若干步算法, 会转会成一串数字:

而最终这串数子,包换1个链的编码,加入这个号码是5.
当然如果是硬解析,则server process还会解析这个sql,并得出执行计划写到这个chunk上.

如下图
Shared pool内存块组成结构及4031错误原因分析 - 饥民 - 饥民2011
 


7. 软解析和硬解析
     由上图得知, 每一条sql语句总会经过运算得到1个chain号码.

1.所以当某条sql语句进入shared pool时.    系统会首先计算出对应这个sql的chain号码(上图动作1)
2. 然后server process会在library cache对应号码的chain上遍历,寻找有无缓存了这条sql的执行计划的chunk.

3. 如果找不到,则会在Free 空空间搬1个新的chunk挂到 library cache的对应chain上,别解析sql语句得出执行计划写入这个chunk中.这就是硬解析(上图动作2)

4.这时这个session或另一个session 传送来另1个相同的sql语句. 经过运算得出相同的chain号.(动作1)

5.server process还是会在对应chain上遍历,因为之前硬解析过一次,所以这次找到缓存执行计划的chunk了,就直接将该执行机会拿出来用了,这就是软解析,不需执行动作2

8. library cache里面的chain管理.
               由上面分析得知, library cache里与free空间不同,并不是按chunk的大小空间去组成1条chain的,而是按硬解析后sql的运算出来的chain号码来组成1条chain的. 这样更加方便server process去查找缓存

              跟free空间一样, library cache同样有 Library cache latch去维护chain的结构.

9. Rowcache(字典缓存)以用样类似的方式去管理
也是说同样是chain结构. 而且居然rowcache latch了



10. 一些动态数据字典:

10.1 x$ksmsp 这张表 存放了shared pool的每1个chunk的信息.
x$ksmsp的detail信息可以参考这里.

执行select count(1) from x$ksmsp 能查看shared pool chunk总数
Shared pool内存块组成结构及4031错误原因分析 - 饥民 - 饥民2011

这时我们执行一条之前从未执行过的sql语句(会发生硬解析)
Shared pool内存块组成结构及4031错误原因分析 - 饥民 - 饥民2011

这时,再去查看shared pool的chunk数量,发现增加了,也代表硬解析产生了碎片..
Shared pool内存块组成结构及4031错误原因分析 - 饥民 - 饥民2011

也可以理解出, shared pool里面的chunk数量越多(大小固定之下), 碎片就越严重.

加入我们每10分钟执行一次查询, 那么10分钟后的chunk数量 - 10分钟前的chunk数量就是这10分钟增加的chunk数量

随着系统运行,应该没10分钟增加的chunk数量应该会越來越少(缓存数据增多,软解析多).

若某一段时间增加了大量chunk数量,通常代表这段时间发生大量的硬解析.产生了大量碎片.

不过通常我们会利用 v$sysstat 来查看硬解析数量.

 11, 清空shared pool缓存数据.
Alter system flush shared pool;

这条命令用于清空shared pool所有的缓存数据!
通常执行这条命令后, 4031错误就会消失, 但是接下来就会发生大量硬解析,因为缓存都被清空啦.

所以对于4031错误来讲,执行这条命令只是1个治标不治本的方法...  治本方法通常是加大shared pool的大小,也就是加内存啦.
 
  评论这张
 
阅读(474)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017