暂无图片
暂无图片
1
暂无图片
暂无图片
暂无图片

DSI401笔记之Memory Management and Heap Corruption

原创 _ All China Database Union 2024-04-01
419

一、内存管理和堆损坏的概述

  1. Oracle服务器的内存结构
    • PGA:由单个进程分配和使用。
    • UGA:在会话开始时分配,由该会话使用。
    • SGA:在启动时分配,所有进程都可以访问。
  2. 内存的管理
    内存按照所需持久性的不同类别进行分组:
    • PGA内存:仅由分配它的Oracle进程访问,当Oracle进程结束时可以释放。PGA内存在Oracle进程的生命周期内动态增长和缩小。
    • UGA内存:与特定会话关联,仅由当前运行该会话的Oracle进程访问。如果会话可以从一个进程迁移到另一个进程(例如,在多线程服务器环境中),则UGA必须是全局可访问的。UGA内存需求在会话的生命周期内动态增长和缩小。
    • SGA内存:由所有Oracle进程访问。
  3. 堆的实现:堆的实现是平台特定的,例如,在UNIX上,UGA和PGA从进程堆分配;SGA是共享内存,在实例启动时分配。在NT上,SGA、PGA和UGA内存从进程堆分配。
  4. 堆、子堆、区段和块的概念:堆是由一个或多个连续内存区域(称为区段)组成,内存从区段中以块的形式分配。一个堆中的块可以包含另一个堆,这被称为子堆。

二、堆损坏的定义和诊断

  1. 堆损坏的定义
    堆损坏(Heap Corruption)发生在关系型数据库管理系统(RDBMS)中,是指错误的数据被写入内存。这通常是由一个失控的进程错误地更新了错误的内存位置所导致的。
  2. 堆损坏的发生
    堆是内存中用于存储地址的部分,这些地址可以被解释为指向结构或其他地址的指针。这些地址和指针在运行时根据需要不断变化。当一个进程在另一个进程仍然分配有该地址时覆写了这些指针或地址,就会发生堆损坏。当Oracle服务器尝试读取堆的那部分并遇到错误信息时,就会发出错误信号。
  3. 堆损坏的症状
    RDBMS和软件通常工作是可预测的并提供可重复的结果。堆损坏,特别是在共享内存中的堆损坏,破坏了这种可预测性,允许不同的代码区域或进程以不受控制的方式相互作用。这种不可预测性是堆损坏的关键特征。堆损坏通常会导致随机和不一致的崩溃,包括ORA-600错误、UNIX上的核心转储和NT上的GPFs(通用保护故障)。重启实例可能会暂时缓解这些症状,但当引起损坏的进程重新引入损坏时,症状通常会返回。
  4. 堆损坏的诊断
    由于堆损坏可能在被发现前持续一段时间,因此找到损坏的原因可能很困难。在共享内存中,发现问题的通常不是造成损坏的进程,这使得找到原因更加困难。为了识别损坏者,可以使用三种方法强制在损坏点发生故障:_db_block_cache_protect参数、10235事件和10049事件。
  5. _db_block_cache_protect
SQL> @pvalid lock

  PAR# PARAMETER                                          VALUE                          DEFAULT
------ -------------------------------------------------- ------------------------------ -------
   374 _db_block_cache_protect                            FALSE                          DEFAULT
       _db_block_cache_protect                            LOW
       _db_block_cache_protect                            MEDIUM
       _db_block_cache_protect                            TRUE

tanelpoder给出的可能值

  1. 10235

10235 (check memory manager internal structures) event内部诊断事件,当oracle SGA内存堆heap 管理操作发生错误时会触发该检测事件(For the sga heap, the internal error is signaled only when heap checking (event 10235) is enabled),其级别列表如下:

[oracle@nas ~]$ oerr ora 10235
10235, 00000, "check memory manager internal structures"
// *Cause:
// *Action:

List of Levels for Event 10235
Level 1: Check heap before heap is freed.
Level 2: Level 1 + fill allocation and frees with 0xff.
Level 3: level 2 + checks to make sure chunk belongs to heap prior to operation (free, grow, make chunk as
freeable with mark). Scan of extents, could get expensive
Level 4: level 3 + allocates permanent chunks as freeable chunks. This accomplishes two things:
all permanent allocations are in their own chunks and the comments for the permanent chunks appear in a heap dump.
The following levels should be OR'ed in together. For example, in order to use levels 2, 8 and 16,
event 10235 needs to be set to level 26.
Level 8: Check heap on every operation to the heap.
Level 16: Level 8 + check top PGA heap and SGA heap.
Level 32: Level 16 + check all heaps in the top pga heap, recursively; check SGA heap.
Level 64: Level 32 + check SGA heap if started up in single_process=true.
Level 256: align chunks at the bottom of a page and page protect the page that follows the chunk,
to catch writes off the end of a chunk, for all heaps.
Level 512: Like level 256, except for all heaps in the pga heap; so this event is useful for detecting
corruption in the pga heap and pga subheaps. This can also be enabled on specific heaps or chunks with
specific comments.
Level 65536: Enable CPM(Commented PerManent chunk) Keep comment for permanent allocation. It's useful for
detecting memory growth/overrun in permanent space. If you need to investigate the allocations for "library cache",
The combination of event 10049 level 10100 and this event will help to have more descriptive information.

注意只有当怀疑oracle实例存在内存讹误(memory corruption)或者深入研究KGH堆管理内部原理的时候才有必要使用该10235事件,不要在生产库设置该诊断事件!! 不推荐在session会话级别设置该event 可能引起问题,具体的设置方法如下:

alter system set event=' 10235 trace name context forever,level 512 ' scope=spfile;
restart instance;

实际上绝大多数情况下我们不会用到10235 event, 即便是提交有关内存泄露(memory leak)或者内存讹误(memory corruption)的SR后 oracle Support 要求你上传一些heapdump的trace信息, 直接做heapdump转储也已经足够了, 具体用法如下:

alter session set event 'trace name immediate headump_addr level <addr>';

maclean原文
orafaq

  1. 10049
To enable block header and trailer checking to detect corrupt blocks:

event="10210 trace name context forever, level 10"  -- for tables
event="10211 trace name context forever, level 10"  -- for indexes
event="10210 trace name context forever, level 2" -- data block checking
event="10211 trace name context forever, level 2" -- index block checking
event="10235 trace name context forever, level 1" -- memory heap checking
event="10049 trace name context forever, level 2" -- memory protect cursors

原文

三、解决堆损坏的方法

1、使用内存转储来收集证据
  1. heapdump:转储PGA、UGA和SGA。使用方法如下:
    alter session set events immediate trace name heapdump level <level>';
    
    其中<level>指定了要转储的内存区域的级别,例如,1代表Top PGA,2代表Top SGA等。
  2. heapdump_addr:转储特定地址的子堆。使用方法如下:
    alter session set events immediate trace name heapdump_addr <addr>';
    
    <addr>是要转储的子堆的地址。
  3. row_cache:转储字典缓存。使用方法如下:
    alter session set events immediate trace name row_cache level <level>';
    
    <level>指定转储的级别。
  4. buffers:转储缓冲区缓存。使用方法如下:
    alter session set events immediate trace name buffers level <level>';
    
    <level>指定了要转储的缓冲区信息的详细程度。
  5. library_cache:转储库缓存。使用方法如下:
    alter session set events immediate trace name library_cache level <addr>';
    
    <addr>可以指定一个特定的地址,或使用10来获取完整的库缓存转储。
2、观察点(Watchpointing)

在Solaris上,Oracle9i引入了增强的观察点(Watchpointing)功能,这是一种强大的诊断工具,允许开发者和数据库管理员精确地监控和诊断内存访问问题,特别是堆损坏问题。

  1. 启用观察点

    • 通过设置初始化参数using_watchpoint_on = TRUE_use_ism = FALSE来启用观察点功能。这些设置通常在数据库实例的初始化参数文件(例如,init.ora或spfile)中进行配置。
  2. 使用oradebug命令

    • Oracle提供了oradebug工具来帮助DBA执行低级调试任务,包括设置观察点。oradebug命令可以在SQL*Plus会话中执行,以便对特定的内存区域设置观察点。
  3. 编程接口

    • Oracle还提供了编程接口来启用观察点,这对于在自定义代码中动态设置和管理观察点特别有用。这包括创建(ksdxwcwpt)和删除(ksdxwdwpt)观察点的函数。
  4. 使用omen命令

    • 为了获取实例内特定损坏内存地址的所有写访问的时间排序列表,可以使用omen命令。这需要通过Oracle的RDBMS工具目录(通常是$ORACLE_HOME/rdbms/utl)来执行。
3、使用视图监控SGA和PGA堆
SELECT /*+use_nl(h,s)*/ sess.sid, sess.username, h.ksmchds, h.ksmchcom ksmchnam, h.ksmchsiz, h.ksmchcls, h.ksmchpar FROM x$ksmhp h, x$ksmsp s, v$session sess WHERE h.ksmchds = s.ksmchpar AND s.ksmchcls LIKE '%recr%' AND s.ksmchpar != hextoraw(00) AND h.ksmchown = sess.saddr;
SELECT /*+use_nl(h,p)*/ h.ksmchds, p.ksmchcom,h.ksmchcom ksmchnam, h.ksmchsiz, h.ksmchcls, h.ksmchpar FROM x$ksmhp h, x$ksmpp p WHERE h.ksmchds = p.ksmchpar AND p.ksmchcls LIKE '%recr%' AND p.ksmchpar != hextoraw(00);
SELECT /*+use_nl(h,p)*/ h.ksmchds, p.ksmchcom,h.ksmchcom ksmchnam, h.ksmchsiz, h.ksmchcls, h.ksmchpar FROM x$ksmhp h, x$ksmpp p WHERE h.ksmchds = p.ksmchpar AND p.ksmchcls LIKE '%recr%' AND p.ksmchpar != hextoraw(00);
4、动态SGA(Dynamic SGA)
  1. 动态SGA的介绍

    • 动态SGA是Oracle9i引入的一个新特性,它允许在不关闭数据库实例的情况下更改SGA配置。这意味着SGA的组成部分(如缓冲区缓存和共享池)可以根据数据库管理员的命令动态地增长和缩小。
  2. 动态SGA的工作原理

    • SGA的组件可以在响应数据库管理员(DBA)命令的情况下动态地增长和缩小。这是通过分配或释放一种称为“粒度”的连续虚拟内存实现的。
    • 粒度的大小基于SGA_MAX_SIZE参数的值确定。如果估计的SGA大小小于128MB,粒度大小为4MB;否则为16MB。
    • 组件(如缓冲区缓存和共享池)根据粒度边界增长和缩小,粒度的分配和释放情况可以通过V$BUFFER_POOL视图查看。
  3. 更改SGA大小

    • DBA可以通过ALTER SYSTEM命令更改组件的SGA使用量,Oracle会将新的大小四舍五入到最接近的16MB(粒度大小)的倍数,并添加或移除粒度以达到目标大小。
    • 如果Oracle有足够的空闲粒度(内存)来满足请求,增加组件的内存分配的ALTER SYSTEM命令才会成功。
    • 当实例的当前SGA内存量小于SGA_MAX_SIZE时,Oracle可以分配更多的粒度,直到SGA大小达到SGA_MAX_SIZE。
  4. 锁定SGA内存

    • 在支持的平台上,可以通过设置初始化参数LOCK_SGA = TRUE来在启动时锁定SGA使用的所有物理内存。这样做可以防止SGA内存被操作系统交换出去,从而提高性能。
最后修改时间:2024-04-01 09:21:13
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论