mysql 5.7+ 必须禁用 transparent_hugepage,因其后台线程 khugepaged 会强行合并 innodb 分配的匿名内存,打乱内存布局、引发延迟抖动;而 mysql 不调用 madvise(madv_hugepage),thp 对其无效。

MySQL 能用 HugePages,但不是加个配置就生效——不关 THP、不算准页数、不设 memlock 权限,large-pages 会静默退化成 4KB 页,压根不走大页。
为什么 MySQL 5.7+ 必须禁用 transparent_hugepage
MySQL 不调用 madvise(MADV_HUGEPAGE),THP 对它无效;但后台线程 khugepaged 会扫描 InnoDB 分配的匿名内存,强行合并页面,打乱内存布局,引发延迟抖动。
- 检查当前状态:
cat /sys/kernel/mm/transparent_hugepage/enabled,输出含[always]或[madvise]就得处理 - 临时关闭(验证用):
echo never > /sys/kernel/mm/transparent_hugepage/enabled - 永久关闭(生产必需):在
/etc/default/grub的GRUB_CMDLINE_LINUX末尾加transparent_hugepage=never,再执行sudo update-grub && sudo reboot - 验证是否真关掉:
cat /proc/meminfo | grep AnonHugePages必须输出AnonHugePages: 0 kB
怎么算够用的 vm.nr_hugepages 值
只按 innodb_buffer_pool_size 算是常见错误。InnoDB 实际还会用额外内存做 log buffer、additional pool、performance_schema 等,建议总内存 +10% 再除以 Hugepagesize(通常 2048 kB)。
- 查当前页大小:
grep Hugepagesize /proc/meminfo→ 确认是 2048 kB 还是 4096 kB - 假设
innodb_buffer_pool_size = 24G,其他开销约 2G,则总需 ≈ 26G →26 * 1024 / 2 = 13312个 2MB 页 - 写入:
echo 13312 > /proc/sys/vm/nr_hugepages或写进/etc/sysctl.conf后sysctl -p - 注意:
HugePages_Rsvd非零才说明内核已预留成功,HugePages_Free下降才表示 MySQL 真在用
MySQL 启动前必须配的三件事
large-pages 是开关,但没权限、没组、没锁内存,MySQL 进程根本申请不到大页。
- 给 mysql 用户解锁内存上限:
/etc/security/limits.conf加两行:mysql soft memlock unlimitedmysql hard memlock unlimited
然后确认生效:su - mysql -c 'ulimit -l'应输出unlimited - 指定可使用大页的组 ID:
id mysql查 gid(比如 501),再执行echo 501 > /proc/sys/vm/hugetlb_shm_group - my.cnf 中只写
large-pages,**不能带等号或值**,例如不能写large-pages=1,否则 MySQL 忽略该配置
怎么确认 MySQL 真正在用 HugePages
别只看 /proc/meminfo 里 HugePages_Free 变少了——那可能是别的进程占的。得从 MySQL 内部验证。
- 启动后执行:
SELECT @@large_pages;→ 必须返回1 - 执行:
SHOW ENGINE INNODB STATUS\G,在输出里搜Large pages used,应看到类似Large pages used: 12288 (24576 KB) - 如果
HugePages_Free没变、@@large_pages是 0、或 status 里没出现Large pages used,说明配置链断在某处,优先重检 THP 和 memlock
最容易被忽略的是:每次调整 innodb_buffer_pool_size 或增减实例后,都得重新算 vm.nr_hugepages 并重载 sysctl,否则新分配的 buffer pool 仍走 4KB 页。











