直接查看 /sys/kernel/mm/transparent_hugepage/enabled 和 /sys/kernel/mm/transparent_hugepage/defrag 文件中被方括号 [] 包围的值,二者需同时为 [never] 才算真正关闭 THP;仅改 enabled 而 defrag 仍为 always 或 defer+madvise,khugepaged 仍会后台扫描导致数据库卡顿。

怎么查当前 THP 是不是开着的
直接看 /sys/kernel/mm/transparent_hugepage/enabled 和 /sys/kernel/mm/transparent_hugepage/defrag 两个文件,它们决定 THP 实际是否生效。只改其中一个没用。
运行:cat /sys/kernel/mm/transparent_hugepage/enabledcat /sys/kernel/mm/transparent_hugepage/defrag
输出里方括号 [ ] 包住的值才是当前生效模式。比如 always [madvise] never 表示实际是 madvise;[never] always madvise 才算真正关了。
常见误区是只改 enabled,但 defrag 还在 always 或 defer+madvise,khugepaged 就会继续后台扫描,照样引发数据库卡顿。
临时关 THP(立刻生效,重启失效)
适用于调试、压测或紧急止损,命令必须两条一起执行:
echo never > /sys/kernel/mm/transparent_hugepage/enabledecho never > /sys/kernel/mm/transparent_hugepage/defrag
注意:defrag 设为 never 比设为 always 更彻底——它不仅停掉合并,还禁止后台扫描触发的内存迁移和拆分。
验证:再跑一遍上面两个 cat 命令,两行输出都得显示 never 在方括号里。
永久关 THP(避免 systemd 或 tuned 覆盖)
写 /etc/rc.local 或放脚本里容易被 tuned、cloud-init、systemd-sysctl 覆盖,最可靠的是内核启动参数。
编辑 /etc/default/grub,在 GRUB_CMDLINE_LINUX 行末尾加:transparent_hugepage=never
然后执行:update-grub && reboot
这个参数会覆盖所有运行时设置,包括 enabled 和 defrag 的值,且不依赖任何用户空间服务。
如果必须用 systemd service 方式(比如某些云环境不允许改 grub),要确保它在 multi-user.target 之前启动,并且 Type=oneshot + RemainAfterExit=yes,否则可能被后续服务重置。
数据库进程单独禁用 THP(不全局关时的折中方案)
某些场景(如混合部署、中间件依赖 THP)不能全局关闭,可对数据库进程单独禁用,但要注意 glibc 版本和启动时机。
通用方式(glibc ≥ 2.29):
在数据库启动脚本最开头插入:echo never > /proc/self/transparent_hugepage/enabled
MySQL 配合 jemalloc:
在 my.cnf 中设:innodb_use_sys_malloc = 1malloc_lib = /usr/lib64/libjemalloc.so.2
PostgreSQL:
启动前设环境变量:MALLOC_CONF="thp:never"(需用 jemalloc 编译),或加载 pg_jemalloc 插件。
注意:这种方式只影响该进程及其 fork 出的子进程,且必须在 malloc 第一次调用前执行,晚了就无效。
真正起作用的标志是 /proc/<pid>/smaps</pid> 里 AnonHugePages 长期为 0,而不是看系统级开关是否设成 never。


















