《DB2性能管理与实战》——2.2 数据库管理器共享内存-阿里云开发者社区

开发者社区> 开发与运维> 正文
登录阅读全文

《DB2性能管理与实战》——2.2 数据库管理器共享内存

简介:

本节书摘来自异步社区出版社《DB2性能管理与实战》一书中的第2章,第2.2节,作者: IBM中国开发中心(CDL) 信息管理软件开发部,更多章节内容可以访问云栖社区“异步社区”公众号查看。

2.2 数据库管理器共享内存

DB2性能管理与实战
数据库管理器共享内存由若干个不同的内存区组成,可使用配置参数控制这些区域的大小。图2-2显示了数据库管理器共享内存的分配方式。

2.2.1 实例(数据库管理器)共享内存

每个DB2实例都有一个实例共享内存。实例共享内存是在数据库管理器启动(db2start)时分配的,并随着数据库管理器的停止(db2stop)而释放。这种内存集用于实例级的任务,例如监控、审计和节点间通信。下面的数据库管理器配置(dbm cfg)参数控制着对实例共享内存以及其中个别内存池的限制。

boll 实例内存(INSTANCE_MEMORY)。

boll 监视器堆(MON_HEAP_SZ):用于监控。

boll Audit Buffer(AUDIT_BUF_SZ):用于db2audit实用程序。

boll 对于分区数据库系统,快速通信管理器(FCM)需要足够多的内存空间,FCM_ NUM_BUFFERS的值较大时尤其如此。所需的FCM内存将从FCM缓冲池中进行分配。

image

INSTANCE_MEMORY参数指定为实例管理预留的内存数量。INSTANCE_MEMORY的缺省值为AUTOMATIC。AUTOMATIC设置将导致在激活数据库分区时计算值。计算值介于系统上的物理RAM的75%~95%之间,系统越大,此百分比越高。对于具有内存使用量限制的DB2数据库产品,计算值也会受到产品许可证允许的最大值的限制。对于具有多个逻辑数据库分区的数据库分区服务器,此计算值是除以逻辑数据库分区数而获得的值。

从V9.7 FP1和V9.5 FP5开始,对于没有内存使用量限制的DB2数据库产品,AUTOMATIC设置的计算值不会对实例中分配的内存施加限制。对于V9.7和V9.5 FP4或更低版本,AUTOMATIC设置的计算值表示对于所有DB2数据库产品的限制。

如果INSTANCE_MEMORY被设置为某一个数字,则采用INSTANCE_MEMORY与MON_HEAP_SZ、AUDIT_BUF_SZ和FCM_NUM_BUFFERS的和之间的较大者。这时,对实例内存就施加了一个硬性的限制,而不是软限制。当达到这个限制时,就会收到内存分配错误。出于这个原因,建议将INSTANCE_MEMORY的设置保留为AUTOMATIC。

如果INSTANCE_MEMORY被设为AUTOMATIC,则可以使用下面的命令来确定它的值:

boll db2 attach to instance_name(其中instance_name是实例的名称)

boll db2 get dbm cfg show detail

下面的输出表明有42 MB的内存被预留给实例共享内存集(10313页×4096字节/页):

boll Size of instance shared memory(4KB)(INSTANCE_MEMORY)= AUTOMATIC(10313) AUTOMATIC(10313)

INSTANCE_MEMORY参数只是设置了实例共享内存的限制,它并没有说出当前使用了多少内存。要查明一个实例的内存使用情况,可以使用DB2内存跟踪器工具db2mtrk。

db2start
db2mtrk-i-v
Memory for instance
FCMBP Heap is of size 17432576 bytes
Database Monitor Heap is of size 180224 bytes
Other Memory is of size 3686400 bytes
Total: 21299200 bytes

上面的例子表明,虽然预留给实例共享内存集的内存有42 MB,但在db2mtrk运行时只用到了大约21 MB。

注意:

在某些情况下,db2mtrk显示的大小会大于指定给配置参数的值。在这种情况下,赋予配置参数的值被作为一种软限制,内存池实际使用的内存可能会增长,从而超出配置的大小。
使用ADMIN_GET_MEM_USAGE表函数来获取特定数据库分区或所有数据库分区的DB2实例耗用的实例内存总量。此表函数还会返回当前上限值。

分配快速通信管理器(FCM)共享内存时,将在每个本地数据库分区的INSTANCE_ MEMORY使用中说明该数据库分区在系统的总FCM共享内存大小中所占的份额。

2.2.2 数据库共享内存

每个数据库有一个数据库共享内存集。数据库共享内存是在数据库被激活或者第一次连接的时候分配的。该内存集将在数据库处于非激活状态时释放(如果数据库先前是处于激活状态)或者最后一个连接被断开的时候释放。这种内存用于数据库级的任务,例如备份/恢复、锁定和SQL的执行。

图2-3展示了数据库共享内存集内的各种内存池。括号中显示了控制这些内存池大小的配置参数。

image

阴影方框意味着,在数据库启动的时候,该内存池是完全分配的,否则,就只分配部分的内存。例如,当一个数据库第一次启动时,不管UTIL_HEAP_SZ的值是多少,只有大约16 KB的内存被分配给实用程序堆。当一个数据库实用程序(例如备份、恢复、导出、导入和装载)启动时,才会按 UTIL_HEAP_SZ指定的大小分配全额的内存。

1.主缓冲池
数据库缓冲池通常是数据库共享内存中最大的一块内存。DB2在其中操纵所有常规数据和索引数据。一个数据库必须至少有一个缓冲池,并且可以有多个缓冲池,这要视工作负载的特征、数据库中使用的数据库页面大小等因素而定。例如,页面大小为8KB的表空间只能使用页面大小为8KB的缓冲池。

可以通过CREATE BUFFERPOOL语句中的EXTENDED STORAGE选项“扩展”缓冲池。扩展的存储(ESTORE)充当的是从缓冲池中被逐出的页的辅助缓存,这样可以减少I/O。ESTORE的大小由num_estore_segs和estore_seg_sz这两个数据库配置参数来控制。如果使用ESTORE,就要从数据库共享内存中拿出一定的内存,用于管理ESTORE,这意味着用于其他内存池的内存将更少。

2.隐藏的缓冲池
当数据库启动时,要分配4个页宽分别为4KB、8KB、16KB和32KB的小型缓冲池(大小为16页)。这些缓冲池是“隐藏”的,因为在系统编目中看不到它们(通过SELECT * FROM SYSCAT.BUFFERPOOLS显示不出)。

如果主缓冲池配置得太大,则可能出现主缓冲池不适合可寻址内存空间的情况。这意味着DB2无法启动数据库,因为一个数据库必须至少有一个缓冲池。如果数据库没有启动,那么就不能连接到数据库,也就不能更改缓冲池的大小。出于这个原因,DB2预先分配了4个这样的小型缓冲池。这样,一旦主缓冲池无法启动,DB2还可以使用这些小型缓冲池来启动数据库(在此情况下,用户将收到一条警告[SQLSTATE 01626])。这时,应该连接到数据库,并减少主缓冲池的大小。

3.排序堆的阈值(SHEAPTHRES,SHEAPTHRES_SHR)
如果没有索引满足所取的行的要求顺序,或者优化器断定排序的代价低于索引扫描,那么就需要进行排序。DB2中有两种排序,一种是私有排序,一种是共享排序。私有排序发生在代理的私有代理内存(在下一节讨论)中,而共享排序发生在数据库的数据库共享内存中。

对于私有排序,数据库管理器配置参数 SHEAPTHRES指定了私有排序在任何时刻可以消耗的内存总量在实例范围内的软限制。如果一个实例总共消耗的私有排序内存达到了这一限制,那么为额外传入的私有排序请求所分配的内存将大大减少,这样就会在db2diag.log中看到如下消息。

"Not enough memory available for a(private)sort heap of size size of SORTHEAP. Trying smaller size..."

如果启用了内部分区并行性(intra-partition parallelism)或者集中器(concentrator),那么当DB2断定共享排序比私有排序更有效时,DB2就会选择执行共享排序。如果执行共享排序,那么就会在数据库共享内存中分配用于这种排序的排序堆。用于共享排序的最大内存量是由 _SHR SHEAPTHRES数据库参数指定的。这是对共享排序在任何时刻可以消耗的内存总量在数据库范围内的硬限制。当达到这个限制时,请求排序的应用程序将收到错误SQL0955(rc2)。之后,在共享内存总消耗量回落到低于由 SHEAPTHRES_SHR指定的限制之前,任何共享排序内存的请求都得不到允许。

下面的公式可以计算出数据库共享内存集大致需要多少内存。

数据库共享内存 =(主缓冲池 + 4个隐藏的缓冲池 + 数据库堆 +实用程序堆 + LOCKLIST + 包缓存 + 编目缓存)+(estore的页数×100字节)+ 大约10% 的开销

对于启用了INTRA_PARALLEL或集中器情况下的数据库,共享排序内存必须作为数据库共享内存的一部分预先分配,因而上述公式变为:

数据库共享内存 =(主缓冲池 + 4个隐藏的缓冲池 + 数据库堆 +实用程序堆 + LOCKLIST + 包缓存 + 编目缓存 + SHEAPTHRES_SHR)+(estore的页数×100字节)+ 大约10% 的开销

提示:

为了发现分配给主缓冲池的内存有多少,可以执行下述命令:

SELECT * FROM SYSCAT.BUFFERPOOLS

虽然大多数内存池的大小是由它们的配置参数预先确定的,但下面两种内存池的大小在默认情况下却是动态的。

boll 程序包缓存:PCKCACHESZ = MAXAPPLS * 8

boll 编目缓存:CATALOGCACHE_SZ = MAXAPPLS * 4

boll 活动应用程序的最大数量:MAXAPPLS = AUTOMATIC

将MAXAPPLS设为AUTOMATIC的效果是,允许任意数量的连接数据库的应用程序。DB2将动态地分配所需资源,以支持新的应用程序。因此,包缓存和编目的大小可以随着MAXAPPLS的值而变化。

除了上述参数以外,还有一个参数也会影响数据库共享内存的数量。这个参数就是DATABASE_MEMORY。该参数的缺省值是AUTOMATIC。这意味着DB2将根据以上列出的各内存池的大小来计算当前配置所需的数据库内存量。此外,DB2还将为溢出缓冲区分配一些额外的内存。每当某个堆超出了其配置的大小时,便可以使用溢出缓冲区来满足实例共享内存区内任何堆的峰值需求。

如果 DATABASE_MEMORY被设为某个数字,则采用DATABASE_MEMORY与各内存池之和这两者之间的较大者。

如果DATABASE_MEMORY被设为AUTOMATIC,则可以使用以下命令来显示它的值。

db2 connect to dbname user userid using pwd
db2 get db cfg for dbname show detail

使用db2mtrk工具显示当前使用的内存量:db2mtrk-i-d-v(在Windows中,-i必须指定。在UNIX中,-i是可选的)。

Memory for database:SAMPLE
  Backup/Restore/Util Heap is of size 16384 bytes
  Package Cache is of size 81920 bytes
  Catalog Cache Heap is of size 65536 bytes
  Buffer Pool Heap is of size 4341760 bytes
  Buffer Pool Heap is of size 655360 bytes
  Buffer Pool Heap is of size 393216 bytes
  Buffer Pool Heap is of size 262144 bytes
  Buffer Pool Heap is of size 196608 bytes
  Lock Manager Heap is of size 491520 bytes
  Database Heap is of size 3637248 bytes
  Other Memory is of size 16384 bytes
  Application Control Heap is of size 327680 bytes
   Application Group Shared Heap is of size 57344000 bytes
  Total: 67829760 bytes

2.2.3 应用程序组共享内存

这种共享内存集仅适用于以下环境(对于其他环境,这种内存集不存在)。

boll 多分区(multi-partitioned)数据库。

boll 启用了内部并行(INTRA_PARALLEL)处理的未分区(NON_PARTITIONED)数据库。

boll 支持连接集中器的数据库。

注意:

当 MAX_CONNECTIONS的值大于MAX_COORDAGENTS的值时,连接集中器便被启用。这两个参数可以在数据库管理器配置中找到(使用GET DBM CFG显示数据库管理器配置)。
在以上环境中,应用程序通常需要不止一个的代理来执行其任务。允许这些代理之间能够彼此通信(相互发送/接收数据)很有必要。为了实现这一点,将这些代理放入到一个称作应用程序组的组中。属于相同应用程序组的所有DB2代理都使用应用程序组共享内存进行通信。

应用程序组内存集是从数据库共享内存集中分配的,其大小由APPGROUP_MEM_SZ数据库配置参数决定。多个应用程序可以指派给同一个应用程序组。一个应用程序组内可以容纳的应用程序数可以这样计算:APPGROUP_MEM_SZ / APP_CTL_HEAP_SZ。

在应用程序组内,每个应用程序都有其自己的应用程序控制堆。此外,应用程序组共享内存中有一部分要预留给应用程序组共享堆,如图2-4所示。

image

例1

考虑以下数据库配置。

boll 最大应用程序内存集大小(4KB)(APPGROUP_MEM_SZ)= 40000

boll 最大应用程序控制堆大小(4KB)(APP_CTL_HEAP_SZ)= 512

boll 用于应用程序组堆的内存所占百分比(GROUPHEAP_RATIO)= 70

可以计算出下面的值。

boll 应用程序组共享内存集是:40000页×4KB/页 = 160 MB

boll 应用程序组共享堆的大小是:40000×70% = 28000页×4KB/ 页 = 114MB

boll 该应用程序组内可容纳的应用程序数为:40000/512 = 78

boll 用于每个应用程序的应用程序控制堆为:(100-70)%×512 = 153×4KB/页 = 0.6MB

不要被APP_CTL_HEAP_SZ参数迷惑。这个参数不是一个应用程序组内用于每个应用程序的各应用程序控制堆的大小。它只是在计算这个应用程序组内可容纳多少应用程序时用到的一个值(此参数在V9.5以后被APPL_MEMORY参数所取代)。每个应用程序的实际应用程序控制堆大小都是通过图2-4中给出的公式计算的,这个公式就是((100- groupheap_ratio)%×APP_CTL_HEAP_SZ)。

因此,groupheap_ratio越高,应用程序组共享堆就越大,从而用于每个应用程序的应用程序控制堆就越小。

例2

假设在一天中最忙的时间里,有200个应用程序连接到例1中所描述的数据库上。由于每个应用程序组可以容纳78个应用程序,因此需要200/78 = 3个应用程序组来容纳总共200个应用程序。这里应确保系统有足够多的RAM来支持这一配置,否则就会发生SQL10003N错误。

2.2.4 代理私有内存

每个DB2代理进程都需要获得内存,以执行其任务。代理进程将代表应用程序使用内存来优化、构建和执行访问计划、执行排序、记录游标信息(例如位置和状态)、收集统计信息等。为响应并行环境中的一个连接请求或一个新的SQL请求,要为一个DB2代理分配代理私有内存。

代理的数量受下面两者中的较低者限制。

boll 所有活动数据库的数据库配置参数MAXAPPLS的总和,这指定了允许的活动应用程序的最大数量。

boll 数据库管理器配置参数MAXAGENTS的值,这指定了允许的最大代理数。

代理私有内存集由以下内存池组成,这些内存池的大小由括号中的数据库配置参数指定。

boll Application Heap(APPLHEAPSZ)

boll Sort Heap(SORTHEAP)

boll Java Interpreter Heap(JAVA_HEAP_SZ)

boll Agent Stack Size(AGENT_STACK_SZ)(仅适用于Windows)

前面曾提到,私有内存是在一个DB2代理被“指派”执行任务时分配给该代理的。那么,私有内存何时释放呢?答案取决于dbm cfg参数NUM_POOLAGENTS的值。该参数的值指定任何时候可以保留的闲置代理的最大数目。如果该值为0,那么就不允许有闲置代理。只要一个代理完成了它的工作,这个代理就要被销毁,它的内存也要返回给操作系统。如果该参数被设为一个非零值,那么一个代理在完成其工作后不会被销毁。相反,它将被返回到闲置代理池,直到闲置代理的数目到达NUM_POOLAGENTS指定的最大值。当传入一个新的请求时,就要调用这些闲置代理来服务该新请求,这样就减少了创建和销毁代理的开销。

当代理变成闲置代理时,它仍然保留了其代理的私有内存。这样设计是为了提高性能,因为当代理被再次调用时,它便有准备好的私有内存。如果有很多的闲置代理,并且所有这些闲置代理都保留了它们的私有内存,那么就可能导致系统内存耗尽。

本文仅用于学习和交流目的,不代表异步社区观点。非商业转载请注明作译者、出处,并保留本文的原始链接。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

分享:
开发与运维
使用钉钉扫一扫加入圈子
+ 订阅

集结各类场景实战经验,助你开发运维畅行无忧

其他文章
最新文章
相关文章