暂无图片
暂无图片
3
暂无图片
暂无图片
暂无图片

简单聊聊ORA-4031

白鳝的洞穴 2020-10-20
1294
二十年前,ORA-4031是DBA面临的最为棘手的问题之一,因此ORA-4031和ORA-1555成为DBA两大经典问题,经常被面试官使用。因为那时候对Oracle内部原理的了解不是很深,因此对ORA-4031的理解也较为肤浅,仅仅能够通过一些案例作为分析的参考。后来,随着对共享池的了解越来越深入,对ORA-4031的成因以及分析处置方法就逐渐完善起来了。

要想弄明白ORA-4031,那么我们必须首先了解共享池的结构以及共享池的内存分配。和大多数共享内存一样,共享池也是以堆(HEAP)的方式进行管理的,在ORACLE中,关于内存堆的管理被简称为KGH([K]ernel layer [G]eneric Layer  [H]eap management以KGH开头的FIXED TABLE(一般以X$开头,实际上是内存中的数据结构)视图以及函数都是与堆管理相关的。于共享内存管理的FIXED TABLE都是以KSM([K]ernel layer [S]ever layer [M]emory management)。

和所有的堆管理一样,共享池也一定存在分配,归还,碎片,回收等存在。为了确保共享池的效率更高,Oracle需要让那些常用的共享池内存尽可能多的保留在内存中不被回收,而让那些一次性使用的内存尽快被老化后回收,从而确保共享池有足够的空闲空间来应对某个高峰期的使用。因此说共享池内存应该保有一定的空闲空间。虽然说共享池的空闲空间不足时可以通过回收内存的方式获得所需的内存,但是回收内存是需要一定的开销的。因为消费者申请的空间必须是连续的,而经过较长时间使用的共享池会因为大量的小内存分配而变得碎片化,也就是缺少连续的可用空间,哪怕进行了十分深度的内存回收,也可能无法找到较大的连续内存空间可用被再分配。因此对于一些稍微大一点的空间申请需求,就有会失败。此时ORACLE就会记录一个ORA-4031。

在SGA自动管理技术没有出现之前,一旦出现ORA-4031问题,那么这个错误是无法恢复的,本次操作只能失败。而那时候又正好是内存十分金贵的时期,我们的共享池往往只有几百M甚至几十M的大小,偶尔出现ORA-4031就很难避免了。如果出现ORA-4031的请求来自于一个十分重要的后台进程操作,那么这种情况,很可能就会导致数据库宕机。所以十多年前,处置ORA-4031是十分考验DBA水准的事情。随着SGA自动管理技术的出现,如果出现无法在共享池的HEAP中分配一个足够大的连续空间的时候,系统还有另外一个选择,就是动态扩展SHARED POOL,从而让内存分配不会最后失败。因此,现在我们遇到因为ORA-4031导致宕机的情况十分少了。不过ORA-4031仍然经常存在。有一个十分经典的脚本可以查看这种情况:

column indx heading "indx|indx num"

column kghlurcr heading "RECURRENT|CHUNKS"

column kghlutrn heading "TRANSIENT|CHUNKS"

column kghlufsh heading "FLUSHED|CHUNKS"

column kghluops heading "PINS AND|RELEASES"

column kghlunfu heading "ORA-4031|ERRORS"

column kghlunfs heading "LAST ERROR|SIZE"

select

  indx,

  kghlurcr,

  kghlutrn,

  kghlufsh,

  kghluops,

  kghlunfu,

  kghlunfs

from

  sys.x$kghlu

where

  inst_id = userenv('Instance')

实际上,我们的后台还是继续在出现ORA-4031,只是新的SGA管理机制大多数情况的ORA-4031对我们而言不可见了而已。不过有些情况下,哪怕启用了SGA自动管理,也依然会出现ORA-4031。这是因为共享池碎片化太严重了,SGA在做自动RESIZE的时候也无法快速供给内存给共享池,此时我们依然会看到ORA-4031错误。那么我们如何进行分析呢?前几天老白正好遇到一个这样的案例,通过报错会话的日志信息,我们可以进行分析,在这个TRACE中,有一个TOP MEMORY使用详情的内容,我们根据这一节的TRACCE分析共享池的内存都被用在哪了,这有助于我们快速定位故障点:

从这个案例来看,空闲内存站的比例还不低,大约有1/4,而为什么会出现无法分配连续的空间呢?

这是一次性要分配12K多空间的大内存分配申请,而此时应该是共享池碎片十分严重了。为什么会出现这么严重的共享池内存碎片呢?我们看到每个子池的ges resource dynamic占用都是排在第一位的,按理说ges resource不应该占用这么多的空间,因此很可能是和Oracle的BUG有关的问题。我们到MOS上去搜索一下,很快就可以定位问题了。

事实上随着物理内存越来越大,以及自动SGA管理,自动内存管理等技术的发展,因为配置不合理导致的ORA-4031出现的越来越少了,由于内存不足导致的问题更是凤毛麟角。一旦遇到此类问题,很可能大多数情况都是由于BUG导致的。DBA的这一特别棘手的问题也似乎变得很简单了,一些老DBA的屠龙技也很少会有用武之地了。

最后修改时间:2020-10-20 09:14:57
文章转载自白鳝的洞穴,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论