看了一下IBM developer的关于进程结构和内存体系结构的文章,我整理了一下其中的部分内容,并在其中插了一下自己试验的命令和输出,db2我一直没有时间去深入学习和研究,就当这是一篇学习笔记了,供大家参考(未整理完待续...): 内存篇 1.Instance shared memory: 1.1概述 1)每个 DB2 实例都有一个实例共享内存。实例共享内存是在数据库管理器启动(db2start)时分配的,并随着数据库管理器的停止(db2stop)而释放。 这种内存集用于实例级的任务,例如监控、审计和节点间通信。下面的数据库管理器配置(dbm cfg)参数控制着对实例共享内存以及其中个别内存池的限制: 实例内存( instance_memory)。 监视器堆( mon_heap_sz):用于监控。 Audit Buffer( audit_buf_sz):用于 db2audit 实用程序。 Fast Communication buffers ( fcm_num_buffers):用于分区之间的节点间通信。仅适用于分区的实例。 2)$db2 get dbm cfg
..
Size of instance shared memory (4KB) (INSTANCE_MEMORY) = AUTOMATIC
..
Database monitor heap size (4KB) (MON_HEAP_SZ) = 90
..
Audit buffer size (4KB) (AUDIT_BUF_SZ) = 0
..
No. of int. communication buffers(4KB)(FCM_NUM_BUFFERS) = AUTOMATIC
1.2深入 1)instance_memory参数指定为实例管理预留的内存数量。默认值是 AUTOMATIC。这 意味着 DB2 将根据监视器堆、审计缓冲区和 FCM 缓冲区的大小计算当前配置所需的实例内存数量。 2)此外,DB2 还将分配一些额外的内存,作为溢出缓冲区。每当某个堆超出了其配置的大小时,便可以使用溢出缓冲区来满足实例共享内存区内任何堆的峰值需求。在这种情况下,个别堆的设置是 软限制的,它们可以在内存使用的峰值期间进一步增长。 3)如果 instance_memory被设置为某一个数字,则采用 instance_memory与 mon_heap_sz、 audit_buf_sz和 fcm_num_buffers的和之间的较大者。这时,对实例内存就施加了一个硬性的限制,而不是软限制。当达到这个限制时,就会收到内存分配错误。出于这个原因,建议将 instance_memory的设置保留为 AUTOMATIC。 4)[db2inst1@seagull ~]$ db2 attach to db2inst1
Instance Attachment Information
Instance server = DB2/LINUX 9.1.0
Authorization ID = DB2INST1
Local instance alias = DB2INST1
[db2inst1@seagull ~]$ db2 get dbm cfg show detail|grep INSTANCE
Size of instance shared memory (4KB) (INSTANCE_MEMORY) = AUTOMATIC(7808) AUTOMATIC(7808) #表明预分配了约32M的实例内存
5)instance_memory参数只是设置了实例共享内存的限制。它并没有说出当前使用了多少内存。要查明一个实例的内存使用情况,可以使用 DB2 内存跟踪器工具 db2mtrk。
[db2inst1@seagull ~]$ db2mtrk -i -v
Tracking Memory on: 2008/01/04 at 11:24:37 Memory for instance
Database Monitor Heap is of size 65536 bytes
Other Memory is of size 1835008 bytes
Total: 1900544 bytes # 表明实际用了不到2M的实例内存
2.database shared memory
2.1 概述 1)每个数据库有一个数据库共享内存集。数据库共享内存是在数据库被激活或者第一次被连接上的时候分配的。该内存集将在数据库处于非激活状态时释放(如果数据库先前是处于激活状态)或者最后一个连接被断开的时候释放。这种内存用于数据库级的任务,例如备份/恢复、锁定和 SQL 的执行。 2)大致由以下几部分组成(有些是一开始就分配好的,有些是在做某些操作时才分配的): a.main bufferpools b.hidden bufferpools c.catalog cache d.lock heap e.package cache f.shared sort g.database heap(includes log buffer) 3)[db2inst1@seagull db2dump]$ db2mtrk -i -d
Tracking Memory on: 2008/01/04 at 12:04:16
Memory for instance
monh other
320.0K 1.9M
Memory for database: SAMPLE
utilh pckcacheh catcacheh bph (1) bph (S32K) bph (S16K) bph (S8K)
64.0K 256.0K 64.0K 4.2M 704.0K 448.0K 320.0K
bph (S4K) shsorth lockh dbh other
256.0K 0 640.0K 4.1M 128.0K [db2inst1@seagull ~]$ db2mtrk -i -v -d
Tracking Memory on: 2008/01/04 at 11:37:24
Memory for instance
Database Monitor Heap is of size 327680 bytes
Other Memory is of size 1966080 bytes
Total: 2293760 bytes
Memory for database: SAMPLE
Backup/Restore/Util Heap is of size 65536 bytes
Package Cache is of size 262144 bytes
Catalog Cache Heap is of size 65536 bytes
Buffer Pool Heap (1) is of size 4390912 bytes
Buffer Pool Heap (System 32k buffer pool) is of size 720896 bytes
Buffer Pool Heap (System 16k buffer pool) is of size 458752 bytes
Buffer Pool Heap (System 8k buffer pool) is of size 327680 bytes
Buffer Pool Heap (System 4k buffer pool) is of size 262144 bytes
Shared Sort Heap is of size 0 bytes
Lock Manager Heap is of size 655360 bytes
Database Heap is of size 4325376 bytes
Other Memory is of size 131072 bytes
Total: 11665408 bytes
2.2 main bufferpools 1)数据库缓冲池通常是数据库共享内存中最大的一块内存。DB2 在其中操纵所有常规数据和索引数据。 2)一个数据库必须至少有一个缓冲池,并且可以有多个缓冲池,这要视工作负载的特征、数据库中使用的数据库页面大小等因素而定。例如,页面大小为 8KB 的表空间只能使用页面大小为 8KB 的缓冲池。 3)可以通过 CREATE BUFFERPOOL 语句中的 EXTENDED STORAGE 选项“扩展”缓冲池。扩展的存储(ESTORE)充当的是从缓冲池中被逐出的页的辅助缓存,这样可以减少 I/O。 4)ESTORE 的大小由 num_estore_segs 和 estore_seg_sz 这两个数据库配置参数来控制。 5)如果使用 ESTORE,那么就要从数据库共享内存中拿出一定的内存,用于管理 ESTORE,这意味着用于其他内存池的内存将更少。 6)之所以要用到ESTORE,跟可寻址内存(而不是物理内存)的限制有关,我们在后面会加以讨论 2.3 hidden bufferpools 1)当数据库启动时,要分配 4 个页宽分别为 4K、8K、16K 和 32K 的小型缓冲池。这些缓冲池是“隐藏”的,因为在系统编目中看不到它们 (通过 SELECT * FROM SYSCAT.BUFFERPOOLS 显示不出)。 2)如果主缓冲池配置得太大,则可能出现主缓冲池不适合可寻址内存空间的情况。(我们在后面会谈到可寻址内存。)这意味着 DB2 无法启动数据库,因为一个数据库至少必须有一个缓冲池。 3)如果数据库没有启动,那么就不能连接到数据库,也就不能更改缓冲池的大小。由于这个原因,DB2 预先分配了 4 个这样的小型缓冲池。 这样,一旦主缓冲池无法启动,DB2 还可以使用这些小型的缓冲池来启动数据库。(在此情况下,用户将收到一条警告(SQLSTATE 01626))。 这时,应该连接到数据库,并减少主缓冲池的大小。 2.4 排序堆的阈值( sheapthres, sheapthres_shr) 1)如果没有索引满足所取的行的要求顺序,或者优化器断定排序的代价低于索引扫描,那么就需要进行排序。DB2 中有两种排序,一种是私有排序,一种是共享排序。私有排序发生在代理的私有代理内存(在下一节讨论)中,而共享排序发生在数据库的数据库共享内存中。 2)对于私有排序,数据库管理器配置参数 sheapthres指定了私有排序在任何时刻可以消耗的内存总量在实例范围内的 软限制. 如果一个实例总共消耗的私有排序内存达到了这一限制,那么为额外传入的私有排序请求所分配的内存将大大减少。这样就会在 db2diag.log 中看到如下消息:
"Not enough memory available for a (private) sort heap of size size of sortheap. Trying smaller size..."
[db2inst1@seagull ~]$ db2 get dbm cfg show detail|grep -i sheap
Sort heap threshold (4KB) (SHEAPTHRES) = 0 0
3)如果启用了内部分区并行性(intra-partition parallelism)或者集中器(concentrator),那么当 DB2 断定共享排序比私有排序更有效时,DB2 就会选择执行共享排序。如果执行共享排序,那么就会在数据库共享内存中分配用于这种排序的排序堆。 [db2inst1@seagull ~]$ db2 get db cfg show detail|grep -i sheap Sort heap thres for shared sorts (4KB) (SHEAPTHRES_SHR) = 5000 5000 4)用于共享排序的最大内存量是由 sheapthres_shr数据库参数指定的。这是对共享排序在任何时刻可以消耗的内存总量在数据库范围内的 硬限制。 当达到这个限制时,请求排序的应用程序将收到错误 SQL0955 (rc2)。之后,在共享内存总消耗量回落到低于由 sheapthres_shr指定的限制之前, 任何共享排序内存的请求都得不到允许。 2.5 package cache and catalog cache 1)虽然大多数内存池的大小是由它们的配置参数预先确定的,但下面两种内存池的大小在默认情况下却是动态的: a.包缓存: pckcachesz = maxappls * 8 b.编目缓存: catalogcache_sz = maxappls * 4 c.活动应用程序的最大数量: maxappls = AUTOMATIC
[db2inst1@seagull db2dump]$ db2 get db cfg show detail |grep -i maxapp
Package cache size (4KB) (PCKCACHESZ) = (MAXAPPLS*8) (MAXAPPLS*8)
Catalog cache size (4KB) (CATALOGCACHE_SZ) = (MAXAPPLS*4) (MAXAPPLS*4)
Max number of active applications (MAXAPPLS) = AUTOMATIC(40) AUTOMATIC(40)
2.6 database memory 参数 1)除了上述参数以外,还有一个参数也会影响数据库共享内存的数量。这个参数就是database_memory。该参数的缺省值是 AUTOMATIC。这意味着DB2 将根据以上列出的各内存池的大小来计算当前配置所需的数据库内存量。此外,DB2 还将为溢出缓冲区分配一些额外的内存。每当某个堆超出了其配置的大小时,便可以使用溢出缓冲区来满足实例共享内存区内任何堆的峰值需求。 2)如果 database_memory被设为某个数字,则采用 database_memory与各内存池之和这两者之间的较大者。 3)如果 database_memory被设为 AUTOMATIC,则可以使用以下命令来显示它的值:
[db2inst1@seagull db2dump]$ db2 get db cfg show detail |grep -i database_memory
Size of database shared memory (4KB) (DATABASE_MEMORY) = COMPUTED(18080) COMPUTED(18080)
2.7 计算数据库共享内存集大致需要多少内存 1)下面的公式可以计算出数据库共享内存集大致需要多少内存: 数据库共享内存 = (主缓冲池 + 4 个隐藏的缓冲池 + 数据库堆 +实用程序堆 + locklist + 包缓存 + 编目缓存) + (estore 的页数 * 100 字节) + 大约 10% 的开销 2)对于启用了 intra_parallel 或集中器情况下的数据库,共享排序内存必须作为数据库共享内存的一部分预先分配,因而上述公式变为: 数据库共享内存 = (主缓冲池 + 4 个隐藏的缓冲池 + 数据库堆 +实用程序堆 + locklist + 包缓存 + 编目缓存 + sheapthres_shr) + (estore 的页数 * 100 字节) + 大约 10% 的开销 3.application group shared memory 3.1概述 1)这种共享内存集仅适用于以下环境。(对于其他环境,这种内存集不存在。) a.多分区(multi-partitioned)数据库 b.启用了内部并行(intra-parallel)处理的未分区(non-partitioned)数据库。
[db2inst1@seagull sqllib]$ db2 get dbm cfg show detail|grep -i intra_p
Enable intra-partition parallelism (INTRA_PARALLEL) = NO NO
c.支持连接集中器的数据库。 注意:当 max_connections的值大于 max_coordagents的值时,连接集中器便被启用。这两个参数可以在数据库管理器配置中找到。
[db2inst1@seagull db2dump]$ db2 get dbm cfg|grep -i coorda
Max number of coordinating agents (MAX_COORDAGENTS) = (MAXAGENTS - NUM_INITAGENTS)
Max no. of concurrent coordinating agents (MAXCAGENTS) = MAX_COORDAGENTS
Max number of client connections (MAX_CONNECTIONS) = MAX_COORDAGENTS
Number of pooled fenced processes (FENCED_POOL) = MAX_COORDAGENTS
2)在以上环境中,应用程序通常需要不止一个的代理来执行其任务。允许这些代理之间能够彼此通信(相互发送/接收数据)很有必要。为了实现这一点,我们将这些代理放入到一个称作应用程序组的组中。属于相同应用程序组的所有 DB2 代理都使用应用程序组共享内存进行通信 3)应用程序组内存集是从数据库共享内存集中分配的。其大小由 appgroup_mem_sz数据库配置参数决定。
[db2inst1@seagull db2dump]$ db2 get db cfg show detail|grep -i app
Max size of appl. group mem set (4KB) (APPGROUP_MEM_SZ) = 30000 30000
Max appl. control heap size (4KB) (APP_CTL_HEAP_SZ) = 128 128
4)多个应用程序可以指派给同一个应用程序组。一个应用程序组内可以容纳的应用程序数可以这样计算:
appgroup_mem_sz / app_ctl_heap_sz
5)在应用程序组内,每个应用程序都有其自己的 应用程序控制堆。此外,应用程序组共享内存中有一部分要预留给应用程序组共享堆。如下图所示:
3.2深入 1)例1,考虑以下数据库配置: 最大应用程序内存集大小 (4KB) (APPGROUP_MEM_SZ) = 40000 最大应用程序控制堆大小 (4KB) (APP_CTL_HEAP_SZ) = 512 用于应用程序组堆的内存所占百分比 (GROUPHEAP_RATIO) = 70 可以计算出下面的值: 应用程序组共享内存集是: 40000 页 * 4K/页 = 160 MB 应用程序组共享堆的大小是: 40000 * 70% = 28000 4K 页 = 114MB 该应用程序组内可容纳的应用程序数为: 40000/512 = 78 用于每个应用程序的应用程序控制堆为: (100-70)% * 512 = 153 4K 页 = 0.6MB 不要被 app_ctrl_heap_sz 参数迷惑。这个参数不是一个应用程序组内用于每个应用程序的各应用程序控制堆的大小。它只是在计算这个应用程序组内可容纳多少应用程序时用到的一个值。每个应用程序的实际应用程序控制堆大小都是通过 上图中给出的公式计算的,这个公式就是 ((100 - groupheap_ratio)% * app_ctrl_heap_sz)。 因此,groupheap_ratio 越高,应用程序组共享堆就越大,从而用于每个应用程序的应用程序控制堆就越小。 2)例2,假设在一天中最忙的时间里,有 200 个应用程序连接到例 1 中所描述的数据库上。由于每个应用程序组可以容纳 78 个应用程序,因此我们需要 200/78 = 3 个应用程序组来容纳总共 200 个应用程序。这里应确保系统有足够多的 RAM 来支持这一配置。否则就会发生 SQL10003N错误 4.agent private memory 4.1概述 1)每个 DB2 代理进程都需要获得内存,以执行其任务。代理进程将代表应用程序使用内存来优化、构建和执行访问计划,执行排序,记录游标信息(例如位置和状态),收 集统计信息,等等。为响应并行环境中的一个连接请求或一个新的 SQL 请求,要为一个 DB2 代理分配代理私有内存。 2)代理的数量受下面两者中的较低者限制: a.所有活动数据库的数据库配置参数 maxappls 的总和,这指定了允许的活动应用程序的最大数量 b.数据库管理器配置参数 maxagents 的值,这指定了允许的最大代理数
[db2inst1@seagull sqllib]$ db2 get dbm cfg show detail |grep -i maxagent
Max number of existing agents (MAXAGENTS) = 401 400
Max number of coordinating agents (MAX_COORDAGENTS) = 400 (MAXAGENTS - NUM_INITAGENT
3)代理私有内存集由以下内存池组成。这些内存池的大小由括号中的数据库配置参数指定: Application Heap ( applheapsz) Sort Heap ( sortheap) Statement Heap ( stmtheap) Statistics Heap ( stat_heap_sz) Query Heap ( query_heap_sz) Java Interpreter Heap ( java_heap_sz) Agent Stack Size ( agent_stack_sz) (仅适用于 Windows) 4.2深入 1)我们曾提到,私有内存是在一个 DB2 代理被“指派”执行任务时分配给该代理的。那么,私有内存何时释放呢?答案取决于 dbm cfg 参数 num_poolagents的值。 该参数的值指定任何时候可以保留的闲置代理的最大数目。如果该值为 0,那么就不允许有限制代理。只要一个代理完成了它的工作,这个代理就要被销毁,它的内存也要返回给操作系统。如果该参数被设为一个非零值,那么一个代理在完成其工作后不会被销毁。相反,它将被返回到闲置代理池,直到闲置代理的数目 到达 num_poolagents指定的最大值。当传入一个新的请求时,就要调用这些闲置代理来服务该新请求。这样就减少了创建和销毁代理的开销。
[db2inst1@seagull sqllib]$ db2 get dbm cfg show detail|grep -i num_poolagents
Agent pool size (NUM_POOLAGENTS) = 200 200(calculated)
2)当代理变成闲置代理时,它仍然保留了其代理的私有内存。这样设计是为了提高性能,因为当代理被再次调用时,它便有准备好的私有内存。 3)如果有很多的闲置代理,并且所有这些闲置代理都保留了它们的私有内存,那么就可能导致系统耗尽内存。为了避免这种情况,DB2 使用一个注册表变量来限制每个闲置代理可以保留的内存量。这个变量就是 DB2MEMMAXFREE。它的默认值是 8 388 608 字节。这意味着每个闲置代理可以保留最多 8MB 的私有内存。如果有100 个闲置代理,那么这些代理将保留 800MB 的内存,因此它们很快就会耗尽 RAM。您可能希望降低或增加这一限制,这取决于 RAM 的大小。
[db2inst1@seagull sqllib]$ db2set db2memmaxfree=8388608
[db2inst1@seagull sqllib]$ db2set db2memmaxfree
8388608
|