【彭建军】IBM DB2 内存分配与使用策略 (中)
上一篇 /
下一篇 2008-06-19 10:31:35
/ 个人分类:IBM
32 位 AIX 中的 DB2 内存配置
在 32 位的 AIX 上,4GB 的可寻址内存空间被拆分为 16 个段,每段 256MB。 图 6展示了用于一个 DB2 代理进程的 32位 内存地址空间。(假设 DB2_MMAP_READ 和 DB2_MMA_WRITE 这两个 DB2 注册表变量都被设为 NO。如果这两个变量没有设为 NO,则表示方法会有点不同。我们将在后面解释。)
图 6 - AIX 中的 DB2 32 位内存地址空间
段 0 - 预留给 AIX 内核。
段 1 - 预留给 db2sysc 进程。
段 2 - 预留给代理私有内存。
段 3 - 预留给实例共享内存。
段 4 到段 B - 数据库共享内存始于段 4,这些段必须紧挨在一起。所有这 8 个段(2GB)可能都被用于数据库共享内存。但是,下面的每种配置都会从数据库共享内存中拿出一个段(256MB)。
注意: 对于下面的每种配置,DB2 将从数据库共享内存中拿出一个段,这个段始于段 B。
如果数据库是分区的,或者启用了 intra-parallel 或连接集中器,那么数据库共享内存中有一个段被预留给应用程序组共享内存。
Fast Communication Manager (FCM):FCM 用于系统物理节点上不同分区之间的通信。默认情况下,这种通信是通过 UNIX socket 进行的。如果 DB2_FORCE_FCM_BP 被设为 YES,那么 FCM 通信发生在共享内存内。这意味着数据库共享内存中有一个段被预留给 FCM 通信。虽然 FCM 通信变得更快,但是它也令数据库共享内存减少了一个段。
fenced UDF 和存储过程:如果数据库上运行着一个 fenced 函数或过程,那么数据库共享内存中有一个段要预留给 fenced 模式的通信。
如果数据库允许任何本地连接,那么数据库共享内存中有一个段要预留给代理/本地应用程序通信。如果将所有本地连接配置为 loopback 连接,那么就可以为这些连接使用 TCP/IP,而不需要共享内存(即使数据库就在服务器本地)。这样就有效地为数据库共享内存空出一个段来。 然而,如果您不想使用 loopback 解决方案,还有一种方法可以迫使 DB2 选择段 E 来用于代理/本地应用程序通信,这样数据库共享内存就不受影响(即不会减少)。请参阅后面的解释。
如果启用了 ESTORE,那么还要从数据库共享内存中拿出另一个段。因此,如果启用 ESTORE,则应确保它至少是 256MB,否则就不起作用,因为要从数据库共享内存中拿出一个 256 MB 的段来仅用于管理这个 ESTORE。建议将 estore 段的大小( estore_seg_sz)设为 256MB,然后根据可用的内存更改段的数目( num_estore_segs)。
段 C - 预留给 DB2 跟踪使用程序。
段 D 和 F- 预留给 DB2 共享库
段 E - 在默认情况下,这个段是不用的。不过,如果设置 DB2_MMAP_READ=NO 和 DB2_MMAP_WRITE=NO,那么该段用于 DB2 代理以及本地应用程序之间的通信(如 图 6所示)。这将有效地为数据库共享内存一个段。
注意: 为了最大化数据库共享内存的空间,应使用以下注册表变量设置:DB2_FORCE_FCM_BP=NO (该值是默认值),DB2_MMAP_READ=NO,DB2_MMAP_WRITE=NO。
需要从这种结构中了解到的最重要的事情是:
对于禁用了 intra-parallel 的单分区系统,我们可以得到至多 2GB 的空间用于数据库共享内存(段 4 到段 B)。
下面每种配置都将数据库共享内存减少了一个段(256MB):带 fenced UDF 或存储过程的数据库、带本地连接的数据库、DB2_FORCE_FCM_BP=YES 情况下的数据库、支持 intra_parallel、或支持集中器以及分区的数据库,以及启用了 ESTORE 的数据库。
如果允许与数据库进行本地连接,那么应该将 DB2_MMAP_READ 和 DB2_MMAP_WRITE 都设置成 NO,以便使用段 E。否则,任何本地连接都要从数据库共享内存中拿走一个段。
这些限制规定了我们该如何配置数据库共享内存集中的每个内存池。可以使用前面给出的公式来计算数据库共享内存。得到的总和不能超过这个限制。
注意:内存可以分配,释放,也可以当数据库正在运行时在不同区域之间交换。例如,您可以减少 locklist 而增加相同数量的任何一个给定的缓冲池。
使用 svmon 监控 AIX 上的内存使用情况
在 AIX 上,除了 db2mtrk 工具外,还可以使用 svmon 工具来监控 DB2 代理进程的内存消耗情况(需要 root 权限)。这个命令是: "svmon -P PID",其中 PID是 DB2 代理(db2agent 或 db2agentp)的进程 ID。
图 7 展示了 svmon 对于一个名为 db2agent 的进程的示例输出。与这个 db2agent 进程相关的数据库有如下特征:
数据库名是 TEST。
INTRAP_PARALLEL = YES (get dbm cfg)
DB2_FORCE_FCM_BP = YES (db2set -all)
DB2_MMAP_READ=NO, DB2_MMAP_WRITE=NO (db2set -all)
图 7 - svmon 对于一个 DB2 代理进程 (svmon -P 11649046) 的输出
从 图 7中观察到的一些情况:
进程 ID 是 11649046,进程名为 db2agent(左上角)。这个代理被连接到数据库 TEST(数据库的名称在 svmon 输出中已经被截断,只显示了 'TES')。
Esid 列显示已经分配的内存段:
段 4 (绿色)被分配给数据库共享内存。
段 2 (橙色)被分配给代理私有内存。
段 3 (蓝色)被分配给实例共享内存。
段 B (紫色)被分配给应用程序组共享内存,因为数据库支持 intra_parallel。
段 A (粉红色)被分配给 FCM,因为 DB2_FORCE_FCM_BP=YES。
本地连接段被移到段 E(红色)。这是因为 DB2_MMAP_READ 和 DB2_MMAP_WRITE 都被设为 NO。否则,就必须将段 8 用于代理和本地连接通信,因为段 A 和段 B 都已经被占用,而段 9 被预留给 fenced 模式的通信。
观察到的这些情况与 图 6中说明的相匹配。
设置 32 位 AIX 系统上数据和堆栈的 ulimit
我们早先说过, 图 6中的段 #2 是用于代理私有内存的。实际上,并非完全如此。
确切地说,段 #2 被预留给数据和堆栈。数据包含用户数据(即代理私有内存)。而堆栈则包含要执行的指令。在这个 256M 的段中,数据是从地址 0x20000000 向下增长的。而堆栈是从地址 0x2FFFFFFF 向上增长的。为了不让数据和堆栈有冲突,设置它们的限制就十分重要。如果数据和堆栈真的有冲突,那么实例就会崩溃,并产生信号 4 或信号 11。
图 8 - 数据段和堆栈段

数据和堆栈的限制是在 ulimits(/etc/security/limits)中设置的。使用 SMIT 将它们设置成如下值:
Data = 491519, Stack = 32767 (512 字节)
上述值以 512 字节为单位,其中对于数据是 240MB,对于堆栈是 16MB。当使用 "ulimit -a" 显示这两个限制时,显示的值以 1K 字节为单位,而不是以 512 字节为单位。因此这两个值变为:
Data = 245760, Stack = 16384
注意: /etc/security/limits 包含了以 512 字节为单位的限制,而不是以 1 KB 为单位的限制。
32 位 AIX 上与分配数据库共享内存有关的常见问题
初始化数据库共享内存失败可能产生如下问题:
在数据库启动时(激活数据库或第一次连接数据库) - SQL1478W, SQL0987C, SQL1084C。
在运行时 - SQL10003N, SQL1042C。
下面的例子展示了会导致问题的不恰当配置。
例 1 考虑以下配置:(所有页的大小为 4KB)
单分区,禁用集中器,INTRA_PARALLEL OFF,DB2_MMAP_READ=NO,DB2_MMAP_WRITE=NO,无 fenced 函数或过程
IBMDEFAULTBP 450,000 页
UTILHEAP 17,500 页
DBHEAP 10,000 页
LOCKLIST 1000 页
PCKCACHE 5000 页
CATALOGCACHE 2500 页
限制:在此配置中,对于数据库共享内存的限制是 2GB 或 8 个段。
计算:使用公式计算数据库共享内存,我们得到:
数据库共享内存 = (486,000 页 x 4KB/页的总数) x 1.1 (考虑到 10% 的开销) = ~2.1GB = 9 个段
注意:我们会将 4 个隐藏缓冲池排除在计算之外,因为它们太小了,不会产生明显的不同。
问题:这超出了 2GB 的限制。当激活数据库或第一次连接到数据库时,您将收到如下警告:
SQL1478W The defined buffer pools could not be started. Instead, one small buffer pool for each page size supported by DB2 has been started. SQLSTATE=01626
在 db2diag.log 中,您将看到有消息说 DB2 将利用隐藏缓冲池启动。要解决这个问题,可以减少主缓冲池的大小。
例 2 考虑如下配置: (所有页的大小都是 4K)
单分区,无 fenced 函数或过程,INTRA_PARALLEL=ON
IBMDEFAULTBP 300,000 页
UTILHEAP 17,500 页
DBHEAP 10,000 页
SHEAPTHRES_SHR 50,000 页
LOCKLIST 1000 页
PCKCACHE 5000 页
CATALOGCACHE 2500 页
限制: 1.5GB (6 个段)。一个段用于应用程序组内存,因为 INTRA_PARALLEL 是 ON。另一个段用于本地连接,因为 DB2_MMAP_READ 和 DB2_MMAP_WRITE 都被设为 YES (该值是默认值)。
计算:数据库共享内存 = (386,000 页 x 4KB/页的总数) x 1.1 = ~1.67GB = 7 个段
问题:这超出了 1.5GB 的限制。当尝试激活数据库或第一次连接到数据库时,您将得到以下错误消息:
SQL1042C An unexpected system error occurred. SQLSTATE=58004
要解决这一问题:
使用 db2set 将 DB2_MMAP_READ 和 DB2_MMAP_WRITE 设为 NO。这样便迫使 DB2 将段 E 用于本地连接,从而为数据库共享内存空出一个段。
例 3 考虑如下配置: (所有页的大小都为 4K)
IBMDEFAULTBP 250,000 页
INTRA_PARALLEL=ON
UTILHEAP 17,500 页
DBHEAP 10,000 页
SHEAPTHRES_SHR 20,000 页
LOCKLIST 1000 页
PCKCACHE 5000 页
CATALOGCACHE 2500 页
存在 Fenced UDF
限制: 以下各占一个段:Intra-parallel ON,本地连接,以及 fenced UDFB。这样还剩下 5 个段,或者 1.25G 给数据库共享内存。
计算:
数据库共享内存 = (306,000 页 x 4KB/页的总数) x 1.1% = ~1.35GB = 6 个段
问题: 引用了 fenced UDF 的查询就会失败,并返回错误 sql10003C。要解决这个问题,可以在 unfenced 模式下运行 UDF,或者将数据库共享内存减少至不多于 5 个段。
待续……
相关阅读:
- 【原】Window里如何在导出时给文件加上日期 (diablo2, 2008-2-20)
- 【原】【实验】DB2V9.5恢复实验 (diablo2, 2008-4-02)
- DB2 DB重定向恢复 (grateful428, 2008-6-03)
- 【kamus】DB2 V9.5 - Starting (idba, 2008-6-05)
- DB2 分区特性 (ploughboy, 2008-6-17)
- 【黄耀华、郝庆运】使用 DB2 pureXML 模拟社会网络 (Social Networks) 应用 (ploughboy, 2008-6-18)
- 【彭建军】DB2 在线增量备份数据库、还原增量备份数据库、前滚恢复数据库脚本 (ploughboy, 2008-6-19)
- 【彭建军】DB2 使用重定向恢复数据库 (ploughboy, 2008-6-19)
- 【彭建军】不同平台之间的 DB2 数据库迁移一例 (ploughboy, 2008-6-19)
- 【彭建军】IBM DB2 内存分配与使用策略 (上) (ploughboy, 2008-6-19)
导入论坛
引用链接
收藏
分享给好友
推荐到圈子
管理
举报
TAG:
db2
内存分配与使用