下面的例子展示了会导致问题的不恰当配置。
例 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 个段。
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 命令的一个示例输出。
