【彭建军】IBM DB2 内存分配与使用策略 (下)

上一篇 / 下一篇  2008-06-19 10:34:05 / 个人分类:IBM

32-位 Sun Solaris Version 2.6 及及其更高版本中的 DB2 内存配置
        
        在 AIX 中,每个段的大小都是 256MB,而在 Solaris 中则有所不同,其内存段的大小不是固定的。32 位 Solaris 可寻址内存结构如 图 9所示。 
        
        图 9 - 32 位 Sun SolarisDB2 中的 32 位内存地址空间
        

        
        从 0x0 到 0x00010000 之间的地址不能使用。第一个段始于 0x00010000,这个段被预留给 db2sysc 可执行程序和代理私有内存。在缺省情况下,这个段结束于 0x10000000,因而这个段总共是 256MB。(我们可以通过设置 DB2DBMSADDR DB2 注册表变量使这个段更大一些,见后面)。在这个段内,db2sysc 可执行程序只占用很小的一片内存,剩下的用于代理私有内存(200MB+)。
        
        在默认情况下,实例共享内存的起始地址固定于 0x10000000。不过,也可以将其改为一个更高的地址,以便有更多的空间留给代理私有内存。例如,如果实例共享内存始于 0x12000000,而不是 0x10000000,那么就有 0x12000000 减去 0x10000000 即 32MB 的额外内存被用于代理私有内存。要做到这一点,可以将 DB2DBMSADDR DB2 注册表变量设为如下值: 
        
        db2set DB2DBMSADDR=0x12000000 
        
        注意: DB2DBMSADDR 值的范围是从 0x10000000 到 0x10FFFFFF,每次递增 0x10000。 
        
        实例共享内存的结束地址是不固定的。这意味着实例共享内存可能会很大。紧接着实例共享内存的是数据库共享内存。因为实例共享内存的结束地址不固定,所以数据库共享内存的起始地址也是不固定的。
        
        在数据库共享内存之后的是用于 DB2 跟踪、共享库和堆栈(即将执行的指令)的内存。在 AIX 中,堆栈和代理私有内存共享相同的内存段,而在 Solaris 中则有所不同,其中代理私有内存和堆栈分别使用不同的内存段。因此,这里不存在两者之间发生冲突的风险。
        
        由于这些内存段的大小不是固定的,我们只能估计实例共享内存和数据库共享内存的大小为: 
        
        4GB - 代理私有内存 - DB2 跟踪 - DB2 共享库 - 堆栈 
        
        注意这个数量同时还包括实例共享内存和数据库共享内存,并且它们的内存段必须是邻接的。为了看一看实际中如何使用内存,可以对 db2sysc 或 db2agent 进程的 ID 运行 /usr/proc/bin/pmap 命令(以 root 的身份)。
        
        注意:在 Solaris 中,当使用 "pe -ef | grep instance_name" 命令显示 DB2 进程时,所有进程都作为 db2sysc 进程显示。可以使用 db2ptree命令来以“真实”名称显示 DB2 进程。 图 9展示了 pmap 命令的一个示例输出。 
        
        图 10 - pmap 命令对于 db2sysc 进程的示例输出(/usr/proc/bin/pmap -x 15444)   


        
        从 图 10 中可以观察到下面一些情况: 
        
        从 0x00010000 到 0x023F8000 这一部分被预留给 db2sysc 可执行程序(~36MB)。 
        橙色的那部分(堆),即从 0x023F8000 到 0x10000000,被用于代理私有内存(~220MB)。 
        实例共享内存,即绿色那部分,始于默认地址 0x10000000。这意味着没有设置 DB2DBMSADDR。 
        所有 3 个绿色的段被用于共享内存,包括实例共享内存和数据库共享内存。pmap 输出并没有说出哪一个段是实例共享内存,哪一个段是数据库共享内存。我们只知道,数据库共享内存在 0xFE002000 结束,因为从这个地址开始的是一个用于匿名内存的段。因此,实例共享内存和数据库共享内存总共的大小是 0xFE002000 - 0x10000000 = 3,992,985,600 字节 = ~3.7 GB。 
        从 0xFFBC0000 到 0xFFFFFFFF 是用于堆栈的内存段(~4MB)。
        注意:在 32 位 Solaris 中,我们通常将 DB2 数据库共享内存限制在大约 3.5 GB。 
        
        如果设置了 DB2DBMSADDR 注册表变量,那么实例共享内存将从该变量指定的地址开始。下面的例子展示了这一点是如何实现的。
        
        例子 设置 DB2DBMSADDR 注册表变量: 
        
        db2set DB2DBMSADDR = 0x12000000 
        db2stop 
        db2start (需要重新启动实例,以使更改生效)。
        获得 db2sys 进程的进程 ID 
        
        ps -ef | grep sylviaq ('sylviaq' 是实例名)。
        -ef | grep sylviaq 
        sylviaq 13166 1 0 13:09:12 pts/2 0:00 /export/home/sylviaq/sqllib/bin/db2bp 13049C11221 5 
        sylviaq 13263 13256 0 13:11:02 ? 0:00 db2sysc 
        sylviaq 13265 13256 0 13:11:03 ? 0:00 db2sysc 
        sylviaq 13257 13254 0 13:10:59 pts/3 0:00 -ksh 
        sylviaq 13256 13253 0 13:10:59 ? 0:00 db2sysc 
        sylviaq 13262 13256 0 13:11:00 ? 0:00 db2sysc 
        sylviaq 13360 13049 0 13:11:41 pts/2 0:00 grep sylviaq 
        sylviaq 13264 13256 0 13:11:02 ? 0:00 db2sysc 
        sylviaq 13266 13261 0 13:11:03 ? 0:00 db2sysc
        以 root 的身份 cd 到 /usr/proc/pmap,并对任何 db2sysc 进程运行 pmap: 
        
        ./pmap -x 13263 
        
        pmap 输出: 
        
        13263: db2sysc 
        Address Kbytes Resident Shared Private Permissions Mapped File 
        00010000 35808 4064 1608 2456 read/exec db2sysc 
        02316000 896 168 48 120 read/write/exec db2sysc 
        023F6000 744 264 8 256 read/write/exec [ heap ] 
        12000000 243472 243472 - 243472 read/write/exec/shared [shmid=0xbc3] 
        21000000 22512 22512 - 22512 read/write/exec/shared [shmid=0xbc4] 
        FCC00000 8328 8328 - 8328 read/write/exec/shared [shmid=0xa96] 
        FE002000 8 - - - read/write/exec [ anon ]
        注意,实例共享内存现在从 0x12000000 开始,而不是从默认地址 0x10000000 开始。代理私有内存的大小(由 'heap' 标出)从 220MB ( 图 10)增加到了 252 MB。(0x12000000 - 0x023F6000 = 0xFC0A000 = 264282112 (十进制) = ~252MB) 
        
        您可能注意到, 图 9中给出的 4GB 地址空间没有包括任何内核内存。这就对了,在 Solaris 中,内核有其自己的地址空间,该地址空间与进程的地址空间是分开的。这样就将更多的空间留给了其他内存集,例如数据库共享内存。 
        
        虽然与 AIX 相比,在 Solaris 中我们有更大的地址空间用于数据库共享内存(在 AIX 上是 2GB),但是在 Solaris 上所有共享内存都是固定在物理 RAM 中。如果 RAM 比较小,那么对于可以并发运行的数据库数目就有很大的影响。请参阅 “Sun Solaris 中与分配数据库共享内存有关的常见问题”一节中的例 2。
        
        需要从这种结构中了解到的最重要的事情是: 
        
        与 AIX 不同,Solaris 的内存段其大小不是固定的。我们可以通过设置 DB2DBMSADDR DB2 注册表变量,将实例共享内存移到更高的地址,从而增加代理私有内存。 
        数据库共享内存的限制大约是 3.5GB。 
        功能内存与 RAM 固定,因而不能交换出去。
        32 位 Sun Solaris 中与分配数据库共享内存有关的常见问题
        
        没有充分配置内核参数以及初始化数据库共享内存失败可能导致如下失败: 
        
        在数据库启动时(激活数据库或第一次连接到数据库) - SQL1478W, SQL1084C, hang condition 
        在运行时 - SQL2043N, 挂起条件
        在 Solaris 系统中,DB2 提供了一个叫做 db2osconf的工具。该工具根据系统的大小对内核参数的值给出建议。对于一个给定的系统,建议的值要足够高,以便能够容纳最合理的工作负载。 
        
        最常见的未能正确设置的内核参数是 shmmax。该参数按字节指定系统中可以分配的共享内存段的最大大小。如果把 DB2 配置成创建大于这个值的数据库共享内存,那么请求就会失败。其他要知道的内核参数是 shmseg和 shmmni。 
        
        Solaris 中另一个与分配数据库共享内存有关的常见问题是由于这样的一个事实导致的,即共享内存段的所有页都是固定在物理 RAM 中的。如果在 RAM 中没有足够的空闲页可用,或者没有足够的可以被 OS 为满足数据库段而调出的其他页,那么启动数据库的请求就会遭到失败。
        
        下面的例子展示了会导致问题的不恰当配置。
        
        例 1 考虑如下配置: (所有页的大小都为 4K)
        
        服务器: 
        
        服务器上的物理 RAM 16GB 
        shmsys:shminfo_shmmax = 2097152 (2GB)
        数据库: 
        
        IBMDEFAULTBP 400,000 页 
        UTILHEAP 17,500 页 
        DBHEAP 30,000 页 
        LOCKLIST 1000 页 
        PCKCACHE 5000 页 
        CATALOGCACHE 2500 页
        限制: DB2 发出的任何创建大于 shmmax 值(这里是 2GB)的数据库共享内存集的请求都将失败,并返回一个 out of memory type 错误。
        
        计算: 
        
        数据库共享内存 = (456,000 页 x 4KB/页) x 1.1 = ~2.0GB 
        
        问题: 可能仍然可以激活数据库或者连接到数据库。但是,尝试运行一个应用程序时可能返回如下错误消息: 
        
        SQL1224N A database agent could not be started to service request, or was terminated as a result of a database system shutdown or a force command. SQLSTATE=55032 
        
        这是 DB2 经常返回的一个错误。不过,如果不是在 AIX 服务器上,而是在 UNIX 服务器上,那么这就很可能与内存资源问题有关。特别地,可能是内核参数没有进行适当的调优。
        
        为解决这个问题,可以适当地配置内核参数。设置: 
        
        shmsys:shminfo_shmmax = 15099494 (~90% of 16GB) 
        
        例 2 考虑如下配置: (所有页的大小都为 4K)
        
        服务器上的物理 RAM 是 1 GB。
        
        数据库 A: 
        
        IBMDEFAULTBP 137,500 页 
        INTRA_PARALLEL ON 
        UTILHEAP 10,000 页 
        DBHEAP 10,000 页 
        SHEAPTHRES_SHR 20,000 页 
        LOCKLIST 1000 页 
        PCKCACHE 5000 页 
        CATALOGCACHE 2500 页 
        APPGROUP_MEM_SZ 20,000 页
        数据库 B: 
        
        IBMDEFAULTBP 92,500 页 
        INTRA_PARALLEL ON 
        UTILHEAP 5,000 页 
        DBHEAP 10,000 页 
        SHEAPTHRES_SHR 15,000 页 
        LOCKLIST 1000 页 
        PCKCACHE 5000 页 
        CATALOGCACHE 2500 页 
        APPGROUP_MEM_SZ 20,000 页
        限制: 因为共享内存是固定到物理 RAM 的,所以这种内存不会被换出。因此,我们只能分配最多 1GB (可用的物理 RAM)的共享内存给数据库使用。
        
        计算: 
        
        数据库 A 共享内存 = (186,000 页 x 4KB/页) x 1.1% = ~818MB 
        数据库 A 应用程序组内存 = 20,000 页 x 4KB/页 = 80MB 
        数据库 B 共享内存 = (131,000 页 x 4KB/页) x 1.1% = ~576MB 
        数据库 B 应用程序组内存 = 20,000 页 x 4KB/页 = 80MB
        为了启动数据库 A,要求: 818MB + 80MB = ~898MB 
        为了启动数据库 B,要求: 576MB + 80MB = ~656MB
        问题: 假设数据库 A 是激活的。至少有 898MB 的共享内存固定在物理 RAM 中。当尝试激活数据库 B 时,就会碰到如下错误消息: 
        
        SQL1084C Shared memory segments cannot be allocated. SQLSTATE=57019 
        
        如果同时启动数据库 A 和数据库 B,我们将请求至少 1.55GB (898MB + 656MB) 的可用物理 RAM,以便同样地将共享内存固定在 RAM 中。显然,1GB 的 RAM 不够。为解决这一问题: 
        
        尝试减少这两个数据库的缓冲池大小。或者 
        尝试减少应用程序组内存。或者 
        更可能的是,增加更多的物理 RAM。在这种情况下,您将需要至少 1.55GB 的物理 RAM,才能同时启动这两个数据库。
        在这种情况下,按照上面的数据库配置参数,在任何时刻启动某一个数据库(数据库 A 或数据库 B)是可行的,但是不能同时启动两个数据库。这是必须增加更多的物理 RAM。
        
        这个问题在 AIX 中不会出现,因为在 AIX 中共享内存没有固定在物理 RAM 中。在这种场景中,可以启动数据库 B。但是,这意味着数据库 A 的数据库内存必须调出。当一个应用程序访问数据库 A 时,又得将数据库 B 的数据库内存调出。您可以想象未来要发生的调页次数有多少。
        
        例 3 考虑如下配置: (所有页的大小都是 4K) 
        服务器: 
        
        服务器上的物理 RAM 16GB 
        shmsys:shminfo_shmmax = 15099494 (16GB 的 ~90%)
        数据库: 
        
        IBMDEFAULTBP 350,000 页 
        UTILHEAP 17,500 页 
        DBHEAP 10,000 页 
        LOCKLIST 1000 页 
        PCKCACHE 5000 页 
        CATALOGCACHE 2500 页 
        ESTORE_SEG_SZ = 400000 页 
        NUM_ESTORE_SEGS = 1
        计算: 
        
        数据库共享内存 = (386,000 页 x 4KB/页 + 400,000 页的 estore * 100 字节) x 1.1 = ~1.66GB 
        ESTORE memory = 400000 x 4KB = 1.6GB
        问题: 数据库共享内存是 1.66GB。这个数小于 3.35GB 的数据库共享内存限制。shmmax 参数设置得比较恰当。但是在启动数据库时可能返回下面的错误消息!您可以在 db2diag.log 中看到如下错误消息: 
        
        2003-12-04-10.10.13.362027 Instance:db2inst1 Node:000 
        PID:18327(db2agent (SAMPLE) 0) TID:1 Appid:*LOCAL.sample.047844091013 
        oper system services sqloVLMAttachVLMSegment Probe:20 Database:SAMPLE 
        sqloVLMAttachVLMSegment - shmat failed 
        0xFFBE833C : 0x0000000C
        shmat 是一个 UNIX 函数,它将与 shmid(另一个 Solaris 函数)所标识的共享内存相关的共享内存段附加到调用进程的数据段上。shmat 失败于 0x000000C,即 ENOMEM 或可用数据空间不足以容纳共享内存段。
        
        换句话说,不能激活数据库或连接到数据库,因为没有足够的共享内存来满足请求。
        
        那么该怎么办呢?答案在于我们分配 ESTORE 的方式。每个 ESTORE 段必须是一个连续的块。在我们的例子中,我们试图为 ESTORE 分配很大的一块(连续的)内存(1.6GB)。即使有 16GB 的 RAM,它也可能会被分段,从而没有一块连续的 1.6GB 的内存。
        
        为解决这个问题,在数据库配置文件中像下面这样设置 ESTORE 的值: 
        
        ESTORE_SEG_SZ = 40000 页 
        NUM_ESTORE_SEGS = 10
        
        通过设置上面的 ESTORE 值,实际上我们仍然试图为 ESTORE 分配总共 1.6 GB 的内存。然而,我们将尝试为 ESTORE 分配 10 块 160MB 的内存。这样分配的连续空间就要小得多,因此最有可能解决问题。 

        全文完。



TAG: db2 ibm 内存分配 使用策略

 

评分:0

我来说两句

显示全部

:loveliness: :handshake :victory: :funk: :time: :kiss: :call: :hug: :lol :'( :Q :L ;P :$ :P :o :@ :D :( :)

我的栏目

日历

« 2010-03-22  
 123456
78910111213
14151617181920
21222324252627
28293031   

数据统计

  • 访问量: 21487
  • 日志数: 111
  • 建立时间: 2008-03-27
  • 更新时间: 2009-11-12

RSS订阅

Open Toolbar