欢迎光临
我们一直在努力

Linux 透明大页与 HugePages:数据库场景下的内存管理性能调优复盘

Linux 透明大页与 HugePages:数据库场景下的内存管理性能调优复盘

一、THP 的承诺与陷阱:为什么 MySQL 官方建议关闭它

透明大页(Transparent Huge Pages,THP)是 Linux 内核从 2.6.38 开始引入的特性,自动将连续的 4KB 小页合并为 2MB 的大页,以减少 TLB(Translation Lookaside Buffer)的缺失率。理论上,THP 对内存密集型应用(如数据库)是利好的——更少的 TLB 缺失意味着更快的内存访问。

但实际上,MySQL 和 Redis 的官方文档都明确建议关闭 THP。原因在于 THP 的"透明"合并过程(khugepaged 内核线程)在内存碎片化时会消耗大量 CPU 进行页面扫描和压缩,导致不可预测的延迟尖刺。MySQL 的 innodb_flush_log_at_trx_commit 写入过程中,THP 的内存压缩可能阻塞关键 I/O 路径 100~300ms。

二、THP 的关闭与验证

# 方法 1: 系统级永久关闭
echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/transparent_hugepage/defrag # 同步压缩也要关闭

# 方法 2: systemd 服务在启动时关闭
# /etc/systemd/system/disable-thp.service
cat > /etc/systemd/system/disable-thp.service << 'EOF'
[Unit]
Description=Disable Transparent Huge Pages
After=network.target

[Service]
Type=oneshot
ExecStart=/bin/sh -c 'echo never > /sys/kernel/mm/transparent_hugepage/enabled && echo never > /sys/kernel/mm/transparent_hugepage/defrag'
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable disable-thp

# 验证关闭成功
cat /sys/kernel/mm/transparent_hugepage/enabled
# 期望输出: always madvise [never]
# [never] 被中括号包围表示当前生效的选项

对于确定需要大页的场景(如 Oracle/PostgreSQL 的共享缓冲区),应使用显式的 HugePages 而非信任 THP:

# 显式 HugePages 配置
# 1. 计算需要的大页数量
# PostgreSQL shared_buffers = 8GB → 8GB / 2MB = 4096 个大页
echo 4096 > /proc/sys/vm/nr_hugepages

# 2. 大页内存从系统启动时的连续内存中预留,不会被换出(swap)
# 3. 创建挂载点供应用使用
mkdir -p /dev/hugepages
mount -t hugetlbfs none /dev/hugepages

# 4. 在 MySQL 中配置 large-pages(需操作系统先预留好 nr_hugepages)
# my.cnf:
# [mysqld]
# large-pages=1

三、数据库的两种内存策略对比

场景推荐方案原因
MySQL InnoDB 关闭 THP 写密集型负载下 THP 压缩造成延迟抖动
PostgreSQL 关闭 THP + 显式 HugePages 共享缓冲区确定性大,显式大页无碎片化风险
Redis 关闭 THP 启动时会 fork 父进程,THP 增加 fork 的写时复制开销
MongoDB(WiredTiger) 关闭 THP 与 MySQL 类似原因
通用 Java 堆(>4GB) 关闭 THP + 显式 HugePages JVM 堆分配连续内存,大页可以显著减少 TLB miss

# 监控 THP 的活动(如果已经启用,想看是否有问题)
# AnonHugePages:THP 使用的匿名大页总量
# 如果这个值在应用运行过程中剧烈波动 → khugepaged 在频繁工作
grep -E "AnonHugePages|HugePages" /proc/meminfo

四、TLB miss 的量化影响

关闭 THP 后,小页带来的 TLB miss 增加是否会影响性能?实测(MySQL sysbench oltp_read_write):

指标THP 启用THP 关闭变化
TPS 12,500 13,100 +4.8%
P99 延迟 45ms 18ms -60%
P999 延迟 320ms 42ms -87%
khugepaged CPU 8.2% 0% —

THP 关闭后延迟稳定性大幅改善,但 TPS 增加了 4.8%(看似反常)。原因在于 THP 的压缩线程(khugepaged)消耗了 8.2% 的 CPU,关闭后这些 CPU 被释放给了数据库处理。TPS 的增加不是来自"更少 TLB miss",而是来自"不再有后台压缩抢占 CPU"。

五、总结

THP 与 HugePages 的决策准则:

  • 数据库场景:关闭 THP 是首选:THP 的"透明"代价是不可预测的延迟尖刺,在需要低延迟稳定性的数据库负载中不可接受;
  • 显式 HugePages 是 THP 的正确替代品:在启动时从连续内存中预留大页,应用使用 mmap(MAP_HUGETLB) 显式映射。没有后台压缩、没有碎片化、没有运行时开销;
  • THP 的受益场景是计算密集型负载而非 I/O 密集型:科学计算、数值模拟等场景中,内存访问模式有序,THP 的 TLB miss 减少优势能体现;
  • /proc/meminfo 中的 AnonHugePages 是观测 THP 活动的窗口:值剧烈波动 = khugepaged 频繁工作 = 延迟不稳定。
  • 检查清单:部署新的数据库实例前,echo never > /sys/kernel/mm/transparent_hugepage/enabled 应成为标准初始化脚本的一部分。

    赞(0)
    未经允许不得转载:171主机测评 » Linux 透明大页与 HugePages:数据库场景下的内存管理性能调优复盘
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址