Linux 进程通过 C 标准库中的内存分配函数 malloc 向系统申请内存,但是到真正与内核交互之间,其实还隔了一层,即内存分配管理器(memory allocator)。常见的内存分配器包括:ptmalloc(Glibc)、tcmalloc(Google)、jemalloc(FreeBSD)。MySQL 默认使用的是 glibc 的 ptmalloc 作为内存分配器。
内存分配器采用的是内存池的管理方式,处在用户程序层和内核层之间,它响应用户的分配请求,向 *** 作系统申请内存,然后将其返回给用户程序。
为了保持高效的分配,分配器通常会预先向 *** 作系统申请一块内存,当用户程序申请和释放内存的时候,分配器会将这些内存管理起来,并通过一些算法策略来判断是否将其返回给 *** 作系统。这样做的最大好处就是可以避免用户程序频繁的调用系统来进行内存分配,使用户程序在内存使用上更加高效快捷。
关于 ptmalloc 的内存分配原理,个人也不是非常了解,这里就不班门弄斧了,有兴趣的同学可以去看下华庭的《glibc 内存管理 ptmalloc 源代码分析》。
关于如何选择这三种内存分配器,网上资料大多都是推荐摒弃 glibc 原生的 ptmalloc,而改用 jemalloc 或者 tcmalloc 作为默认分配器。因为 ptmalloc 的主要问题其实是内存浪费、内存碎片、以及加锁导致的性能问题,而 jemalloc 与 tcmalloc 对于内存碎片、多线程处理优化的更好。
目前 jemalloc 应用于 Firefox、FaceBook 等,并且是 MariaDB、Redis、Tengine 默认推荐的内存分配器,而 tcmalloc 则应用于 WebKit、Chrome 等。
大型数据库系统的性能调优颇具挑战性。根据 *** 作系统 (OS) 和硬件的不同,有些性能问题可能难以通过常规分析方法(如 AWR 报表)和 *** 作系统工具(如 sar、top 和iostat)来检测。x86 环境中的内存利用率就是一个难以识别的问题,但如果分析和配置得当,可显著提升性能。
想对本文发表评论吗?请将链接发布在 Facebook 的 OTN Garage 页面上。有类似文章要分享?请将其发布在 Facebook 或 Twitter 上,我们来进行讨论。
现在的系统内存更大,内存利用率成为一个亟待解决的重要问题。本文介绍如何最佳配置大型数据库的 x86 系统内存性能。
适用于 x86 平台的虚拟内存架构
与最初时相比,x86 和 x86-64 芯片组的内存架构已经发生巨大变化;但默认内存页面大小却一直未变。遇到使用大量内存的大型应用程序(如数据库)时,这可能导致效率低下或开销过大。
x86 架构是一种虚拟内存架构,其允许寻址范围超过硬件中的可用物理内存。这通过允许每个进程拥有自己可寻址的内存来实现。该进程认为此内存是专供自己使用的。这称为进程的虚拟内存。实际上,此内存可以是实际驻留于 RAM 芯片上的物理内存,也可以存储在物理磁盘上被称作交换区 或分页区 的专用区域中。
进程不知道虚拟内存是存储在 RAM 中还是磁盘上;内存由 *** 作系统管理。如果所需内存超过可用物理内存, *** 作系统会将一些内存移出到分页区。这种活动效率极低,是导致性能问题的常见原因。由于磁盘的存取速度远低于 RAM,“分页”的进程会遇到显著的性能问题。
Oracle 数据库和 Linux 内存管理
系统中使用的内存越多,管理该内存所需的资源也就越多。对于 Linux *** 作系统,通过 Linux kswapd 进程和页表内存结构(针对系统中存在的每个进程包含一条记录)实现内存管理。每条记录包含进程使用的每页虚拟内存及其物理地址(RAM 或磁盘)。通过使用处理器的转换旁路缓冲区(TLB,一小块缓存)为该进程提供帮助。
当大量内存用于 Oracle 数据库时, *** 作系统将消耗大量资源来管理虚拟地址到物理地址转换,其结果往往是一个非常大的页表结构。由于每条页表条目包含进程正在使用的所有内存页面的虚拟地址到物理地址的转换,因此对于非常大的系统全局区 (SGA),每个进程的页表条目都可能很大。例如,使用 8 GB 内存的 Oracle 数据库进程的页表条目将达 8 GB/4 KB(即 2097152 条记录或页面)。如果有 100 个 Oracle 数据库会话/进程,则将页面数乘以 100。您可以看到,要管理的页面数量巨大。
同样, *** 作系统使用页表条目管理系统中进程所用的内存。在 Linux 中,执行此管理的 *** 作系统进程被称作 kswapd,可在 *** 作系统工具中找到。
TLB 缓存将缓存页表条目来提高性能。典型的 TLB 缓存可保存 4 到 4096 个条目。对于数百万甚至数十亿个页表条目,这种缓存就不够用了。
如上所述,对于使用大型 SGA 的系统,页表结构可能会变得非常大。清单 1 中的 Linux 系统输出示例显示页表条目占用了 766 MB 的 RAM。这可能导致显著的系统开销。我亲眼见过数 GB 的页表条目。
HugePages 是 Linux *** 作系统的一个内核特性,让 *** 作系统可以支持现代硬件架构的大页面容量功能。对于 Oracle 数据库,通过启用 HugePages 并使用大页面,可以用一个页表条目代表一个大页面,而不是使用许多条目代表较小的页面,从而可以管理更多内存,减少 *** 作系统对页面状态的维护并提高 TLB 缓存命中率。在 Linux 中,大页面大小为 2 MB。
在 Oracle Linux 6 或 Red Hat Enterprise Linux 6 (RHEL 6) 中,可在 /proc/meminfo 中找到分配的 HugePages 数,如清单 1 所示:
[root@ptc1 ~]# cat /proc/meminfo
MemTotal: 4045076 kB
MemFree: 14132 kB
Buffers: 656 kB
Cached:1271560 kB
SwapCached: 6184 kB
Active:2536748 kB
Inactive: 625616 kB
HighTotal: 0 kB
HighFree:0 kB
LowTotal: 4045076 kB
LowFree: 14132 kB
SwapTotal: 1052216 kB
SwapFree:0 kB
Dirty: 0 kB
Writeback: 0 kB
Mapped:2036576 kB
Slab:49712 kB
CommitLimit: 3074752 kB
Committed_AS: 8054664 kB
PageTables: 766680 kB
VmallocTotal:536870911 kB
VmallocUsed:263168 kB
VmallocChunk:536607347 kB
HugePages_Total: 0
HugePages_Free: 0
Hugepagesize: 2048 kB
清单 1
在 Oracle Linux 6 中,分配的 HugePages 略有不同,如清单 2 所示:
AnonHugePages: 0 kB
HugePages_Total:1508
HugePages_Free: 60
HugePages_Rsvd: 57
HugePages_Surp:0
Hugepagesize: 2048 kB
DirectMap4k: 10240 kB
DirectMap2M:16766976 kB
清单 2
Oracle Linux 6 HugePages 值如下所示:
AnonHugePages。匿名 HugePages 数量。Oracle Linux 6.5 中已删除此计数器。与透明 HugePages 有关。(有关透明 HugePages 的详细信息,请参见“透明 HugePages 和 Oracle 数据库”一节。)
HugePages_Total。HugePages 数量。空间大小为 HugePages 数乘以 2M。
HugePages_Free。池中尚未分配的 HugePages 数量。
HugePages_Rsvd。“reserved”的缩写形式,表示池中已经承诺分配但尚未分配的 HugePages 数量。保留的 HugePages 保证应用程序随时请求都能够从 HugePages 池分配 HugePages,即使系统已经运行一段时间。
HugePages_Surp。“surplus”的缩写形式,表示池中大于 /proc/sys/vm/nr_hugepages 中值的 HugePages 数量。剩余 HugePages 的最大数量由 /proc/sys/vm/nr_overcommit_hugepages 控制。此值为 0 的情况很常见。
Hugepagesize。HugePage 的大小。此参数当前为 2048 或 2 MB。
解决方案
通过在 Linux 中启用 HugePages,可以通过增大页面大小来减少 TLB 条目数。对于 Linux,HugePages 大小为 2 MB。通过为 Oracle 数据库 SGA 选用更大的页面,可大大减少要管理的页面数。
在清单 1 所示示例中,单条记录的虚拟地址到物理地址转换数将从 2097152 减少至 4096。这将减小页表结构的大小,提高 TLB 命中率,并降低 kswapd 使用率。
注:启用 HugePages 可显著提升性能。
在 Linux 中启用 HugePages
在 Linux 中,通过将 Linux 初始化参数 vm.nr_hugepages 设置为您希望为 Oracle 数据库 SGA 提供的 2 MB 页面数来配置 HugePages 功能。设置此参数可通过将其值调大来减少页面数。
注:Oracle Database 11g 中引入的 Oracle 数据库自动内存管理特性与 Linux HugePages 不兼容。HugePages 提供的性能改进优于自动内存管理所提供的易用性。
有关如何实现 HugePages 配置的详细信息,可在表 1 所示的 My Oracle Support 文档中找到。
表 1. My Oracle Support 文档
My Oracle Support 文档 ID
文档名称
1557478.11557478.1“通知:SLES11、RHEL6、OEL6 和 UEK2 内核上禁用透明 HugePages”
361323.1“Linux 上的 HugePages:它是什么……它不是什么”
361468.1“Oracle Linux 64 位上的 HugePages”
749851.1“Linux 上的 HugePages 和 Oracle Database 11g 自动内存管理 (AMM)”
1134002.1“ASMM 和 LINUX x86-64 HugePages 支持”
401749.1“用于计算推荐的 Linux HugePages/HugeTLB 配置的值的 Shell 脚本”
除了配置 vm.nr_hugepages,还可以将可选的 vm.hugetlb_shm_group 参数设置为有权使用 HugePages 的 *** 作系统组。默认情况下,此参数设置为 0,从而允许所有组使用 HugePages。可以将此参数设置为 Oracle 数据库进程所属的 *** 作系统组,如 oinstall。
验证是否已对 Oracle 数据库实例启用大页面
可以通过检查警报日志来验证是否对数据库实例启用了大页面。启动实例时,您应在警报日志中参数列表前面看到如下内容:
****************** Large Pages Information *****************
Total Shared Global Region in Large Pages = 28 GB (100%)
Large Pages used by this instance: 14497 (28 GB)
Large Pages unused system wide = 1015 (2030 MB) (alloc incr 64 MB)
Large Pages configured system wide = 19680 (38 GB)
Large Page size = 2048 KB
透明 HugePages 和 Oracle 数据库
最近,RHEL 6、Oracle Linux 6 和 SUSE Linux Enterprise Server 11 中引入了一个新特性 — 透明 HugePages。透明 HugePages 旨在自动、动态地利用 HugePages。遗憾的是,目前透明 HugePages 与传统 HugePages 联用会出现一些问题,导致性能问题和系统重启。在 My Oracle Support 说明 1557478.11557478.1 中,Oracle 建议不要同时使用透明 HugePages 和 Oracle 数据库。
注:在 Oracle Linux 6.5 版中,已删除透明 HugePages。
总结
通过使用更大的页面,可以减少页表条目数,从而最大程度减少开销。使用 HugePages 可显著提升性能,增加系统中的内存数量和 SGA 大小。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)