Linux 上的 DB2 内存和文件缓存性能调优

Monty Wright , DB2 专家, IBM Advanced Technical Support, IBM

2005 年 10 月 24 日

简介

运行在 Linux 平台上的数据库系统已经成为关键企业应用的基础。DB2 Universal Database(DB2 UDB)拥有精心设计的、Linux 平台独有的特性,从而充分利用了这种平台的优势。

本文总结了 Linux 上与内存的使用和文件缓存相关的一些问题。通过本文可以了解特定的 DB2 特性的优点,从而更好地从 DB2 数据库的角度管理好这些资源。

Linux 上内存的使用

首先我们来讨论一些术语和概念,这对于理解对内存使用的讨论很重要。相对于 64 位地址空间,我们首先来看一下 32 位地址空间这个概念。内存中的每一个字节都必须有一个“地址”,以便让进程可以找到它。这些地址的列表就称作“地址空间”。单独 1 位有两种可能的取值,因此可以指向两个可能的地址 —— 即 2 个字节;32 位有 2^32 种组合,可以为 4,294,967,296 个字节(4 GB)寻址,而 64 位则有 2^64 种组合,可以为 16 EB 寻址。

大多数现代的非 64 位系统都能够创建 36 位的地址空间,从而产生 64 GB 的可寻址内存。但是,并不是每个独立的进程都可以使用这么大的地址空间,只是对于 Linux 操作系统可以使用这么大的地址空间,Linux 操作系统会创建从这些地址到分配给一个进程的地址之间的映射。进程地址仍限于 32 位,以便在不同的内存范围中为各个进程产生地址空间。这使得很多进程可以使用内存量多于 4 GB 的系统。然而,如果两个或更多进程要使用共享内存进行通信,那么它们需要有相同的地址空间,从而限制了它们所能使用的地址。而使用 64 位地址空间的系统实际上是没有这种限制的。

地址空间并不完全用于单个的进程。某些范围的地址空间是专用于特定的进程的,例如内核。这样便为 DB2 留下了大约 2 GB 的地址空间,这正是本文关注的焦点。

注: 有些编程技术可以访问进程地址空间以外的内存,即扩展存储(extended storage)。这个扩展的区域只能用作缓存,要操纵其中的数据,必须将数据移回地址空间。Linux 上的 DB2 目前还不支持这些技术。

在一般情况下,Linux 使用一个文件系统缓存为磁盘请求进行缓冲和读写。Linux 非常贪婪地执行这个任务,您很快就可以看到,系统中未使用/空闲的内存变得很少。可以削减分配给文件缓存的内存,并转给发出请求的进程,这会减少被缓冲的数据量;但是,读写请求仍然会经过这个更小的文件缓存。分配给所有进程、内核和文件缓存的总内存量就是您的全部工作区(working set)。如果整个工作区超出了系统中的物理 RAM 量,那么 Linux 可以使用磁盘空间作为 RAM 的虚拟扩展,即交换空间(swap space)。自然,在这个区域上的读写比内存上的读写要慢得多。

关于内存使用的例子

让我们来看两个使用 Linux free 命令的内存使用例子。该命令显示系统中的空闲内存、已使用的物理内存和交换内存的总量,以及内核所使用的缓冲区。我们将使用 -m 选项,该选项以兆字节为单位显示值,还有 -o 选项,该选项忽略缓冲区信息,以便显示更多的输出。图 1 展示了 free 命令的一个例子。显示的信息如下所示:

  • a – 物理内存总量
  • b – 已使用的内存总量
  • c – 空闲物理内存量
  • d – 文件缓存的大小
  • e – 交换空间的总大小
  • f – 已使用的交换空间
  • g – 空闲的交换空间


图 1. free 命令示例

我是在重启系统“wrightxe”之后不久捕捉这个屏幕的,在此时的系统中,空闲内存(930 MB)占很大的百分比,而用于缓存的内存则很少(28 MB)。图 2 说明了 Linux 文件缓存的贪婪性。


图 2. 文件缓存示例

我将一个大文件 DB2ESEV8.2.tar 中的内容提取到 /dev/null(充当类似黑洞角色的虚设备,实质上是要摒弃所有的写操作)。缓存的大小飙升到 501 MB,接近我在测试中使用的文件的大小(473 MB)。此外,已用内存和空闲内存大致地呈现相同数量的增减。

当 DB2 从磁盘取数据时,它将数据放在一个 DB2 共享内存区域中。共享内存区域的一个作用是充当缓冲区,以减少对磁盘的读操作。然而,通过 Linux 缓存,实质上是双重地缓冲数据。DB2 内存调优的一个目标就是,如果可以增加 DB2 可用的内存,则加大分配给 DB2 缓冲区的内存量,减少 Linux 用作缓存的内存量。

图 3 展示了在应用程序的内存需求下显得力不从心的一个系统。


图 3. 力不从心的系统

关键是看到 totalfreecachedswap 的值之间的关系。首先要注意的是,工作区足够大,能请求 138 MB 的交换空间。与内存总量相比,这是一个很大的量。如果交换空间的使用很常见,或者占很大比例的内存,那么这要么是因为过度地将内存分配给 DB2,要么是因为其他进程或您的机器对于您尝试运行的工作负载力不从心。

可用于确定 DB2 所使用内存量的一个工具是 db2mtrk,这是 DB2 内存跟踪器命令。虽然这个命令有几个选项,不过我们只看 -d 这一个选项,该选项显示数据库级的内存,如图 4 所示。


图 4. DB2 内存跟踪器

输出显示了 SAMPLE 数据库使用的内存。如果还有其他数据库,那么这些数据库对内存的使用情况也会显示出来。最大的值通常在 bph 上,这是 DB2 的缓冲池。这里的输出显示了 5 个缓冲池。实际上,第一个 bph 表示 IBMDEFAULTBP,这是系统上惟一由用户定义的缓冲池。其他 4 个缓冲池是“隐藏的”缓冲池,每个缓冲池对应于一种 DB2 页宽(4 K、8 K、32 K 和 64 K),这些缓冲池用于确保当用户缓冲池的分配失败时,DB2 仍能够运行。在这个例子中,有 201.3 MB 内存被分配给 IBMDEFAULTBP,对于只有 357 MB 内存的系统来说,这是一种过度的分配。DB2 内存跟踪器可以显示关于实例以及 DB2 代理所使用的内存的信息。

为 DB2 UDB 配置 Linux

我常听到的一个问题是,“为了使 DB2 能够很好地在 Linux 上运行,我需要怎样调整 Linux 内核或系统?”我回答说,这没有必要,使用受支持的发行版中的标准内核就可以了。听到这个答案,读者们往往感到很惊讶。实际上,DB2 在启动时会对内核内存作一些调整。DB2 通过对系统的探测来确定当前的配置。下面是在我的系统上写到诊断日志文件中的探测结果。


清单 1. 探测输出



除了关于系统使用的内存总量的信息外,DB2 还确定一些内核参数的值。之后,DB2 调整其中一些参数,并在 DB2 日志文件中记录这些调整。


清单 2. 参数调整



如果您已经为适合自己的需要而调整了参数,对于已经在系统上运行的某个应用程序,DB2 可能不调整这些值。这一点也会记录在 DB2 诊断日志中。如果您不希望由 DB2 自动调整这些参数,那么请参阅在线的 DB2 UDB Information center 中关于修改内核参数(Linux)的小节,以了解如何检查和设置这些参数。(见 参考资料。)

为了加大对系统内存的使用,DB2 自动对系统作进一步的调整。DB2 需要一个连续的地址空间来作为共享内存区域。但是,内核会将共享库的连接地址映射到地址空间靠中间的某个地址,从而限制了连续地址的获得。DB2 将自动偏移这个映射,以获得更大的连续区域。这样可以为数据库共享内存增加 500 MB 的可用内存,从而使内存使用总量从 2 GB 多一点儿增加到 2.2 GB。这是通过修改 mapped_base 地址取得的,该地址指定共享库的连接地址。这只会影响 DB2 进程地址空间,而不会影响整个系统。下面来自 DB2 诊断日志的条目描述了在我系统上发生的这一事件:


清单 3. 进一步的系统调整


DB2 配置调优

从 DB2 V8.2 基础上的最新版本 DB2 V8.2.2(fix pack 9,FP9)开始,下面这些 DB2 特性都得到了支持。虽然其中有很多特性在较早的 V8.1 版本中已经实现了,但为了便于讨论,我将假设系统使用的是 V8.2 版本级别上的 DB2。

AIO

DB2 Asynchronous I/O(AIO) for Linux 与内存的使用只有部分关系。AIO 允许进程在等待 I/O 请求返回时执行其他的工作。DB2 页面清理器可以通过 AIO 来更有效地使用系统资源。要使用 AIO,必须安装 libaio-0.3.96 或更高版本的库,并且内核必须支持 AIO。Kernels 2.6 及以上版本均支持 AIO。如果使用的是 2.4 版本的内核,那么需要与发行版的供应商核对一下。DB2 页面清理器实际上要负责将脏数据或不需要的数据从缓冲池转移到磁盘。这样可以确保缓冲池中有空间用于新的页面。为了在 Linux 启用 AIO,必须设置 DB2 注册表变量 DB2LINUXAIO(使用下面显示的命令)并重新启动 DB2。



AIO 在 OLTP 环境中最能发挥效用。如果您的系统不支持 AIO,那么 DB2 将不会实现 OLTP 特性。请参阅发行说明以获得更多细节。(见 参考资料。)

直接 I/O

DB2 缓冲池与 Linux 文件缓存基本上执行相同的功能,也就是缓存从磁盘读出的数据的拷贝。如前所述,一般情况下,读操作的流程是先将数据读到文件缓存中,然后再复制到缓冲池。结果,系统周期被用于执行复制,并使这两个区域的内存基本上执行相同的功能。对于 Linux 2.6 之前版本的内核,Linux 系统上的文件缓存可能会出差错,需要花费大量的周期来管理文件缓存。

直接 I/O 直接将数据从磁盘读到 DB2 内存区域,完全绕过文件缓存,从而解决了上述问题。这个特性是以表空间为单位启用或禁用的,从而可以有效地使 DB2 中的某些数据使用文件缓存,而另一些数据则绕过文件缓存。在创建或修改表空间时,通过指定表空间选项 NO FILE SYSTEM CACHING就可以启用该选项。下面的例子展示了如何创建或修改表空间,以便使用 NO FILE SYSTEM CACHING 选项。


清单 4. 创建或修改表空间,以便使用 NO FILE SYSTEM CACHING 选项



所有 DB2 表空间都可以使用这个选项,包括系统表空间和临时表空间,以及数据库管理的表空间。惟一的例外是 Linux 原始设备表空间容器,因为它本身就绕过文件缓存。要在 Linux 上建立原始设备,请参阅 DB2 Information Center 中的“Linux raw devices”(见 参考资料)。LOB 和 LONG VARCHAR 数据字段通常不能从直接 I/O 受益,因此将继续使用文件缓存。对于数据库管理的表空间,建议拆开 LOB 数据中的常规数据,将 LOB 数据放在一个很大的表空间中。

向量 I/O

读请求通常要求将“x”个字节放在一个单独的 I/O 缓冲区中。这个 I/O 缓冲区是一段连续的内存,如果这段内存非常大,则必须将它拆分成较小的字节块,并复制到某个应用程序(例如 DB2)使用的其他内存区域中。例如,在响应某个查询时,DB2 可能会将多个区段的数据预取(pre-fetch)到缓冲池中。缺省情况下,一个区段是 32(4 KB)页。在这里,区段被拆分成 4 KB 的字节块(一个个的页),并复制到缓冲池。

向量 I/O 允许分配更小的 I/O 缓冲区。在这个例子中,缓冲区大小是 4 KB。一个单独的向量读操作将填充这些缓冲区,而这些缓冲区是直接与缓冲池中的页相关的,从而不必执行复制。为了在 Linux 上启用向量 I/O,必须设置 DB2 注册表变量 DB2_SCATTERED_IO(如下面的命令所示)并重新启动 DB2。



要了解关于 DB2 向量 I/O 的更多信息,请参阅 DB2 Information Center 中的“DB2 Vector I/O”。

结束语

DB2 与 Linux 紧密集成,并利用最新的 Linux 内存技术。在 Linux 上对 DB2 的内存使用进行调优应该不是件难事。DB2 提供了特定于 Linux 的一些特性,以便充分利用系统资源。本文讨论的问题为打造一个运行良好的 DB2/Linux 系统提供了很好的起点。

参考资料

学习


获得产品和技术


讨论

阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭