如何在大内存服务器上通过配置MySQL的huge pages优化其性能?
- 内容介绍
- 文章标签
- 相关推荐
本文共计892个文字,预计阅读时间需要4分钟。
MySQL 在大内存服务器上启用 `large-pages` 不等同于增加一行配置即生效。多数失败案例根本原因是没有使用上大页 —— 通过 `SHOW VARIABLES LIKE 'large_pages'` 显示 `ON`,但执行 `/proc/meminfo` 里的 `HugePages_Free` 未变、在 `INNODB STATUS` 里也没有 `Large pages used`,即典型静默默认 fallback。
确认内核是否真正支持显式大页(hugetlbpage)
透明大页(transparent_hugepage)和 MySQL 要的显式大页(hugetlbpage)完全不兼容,不能混用。必须确认内核编译时启用了 CONFIG_HUGETLB_PAGE=y:
- 运行
grep -i hugetlb /boot/config-$(uname -r),有输出才表示支持;无输出就得换内核或重编译 - 再看
cat /proc/meminfo | grep -i huge:如果Hugepagesize是空或报错,说明底层未启用;HugePages_Total: 0只是还没分配,不算问题 - 别信
echo 1024 > /proc/sys/vm/nr_hugepages成功就完事——若HugePages_Free不变,大概率是物理内存不连续,尤其在长期运行的生产机上;最稳做法是重启后立刻配
计算并分配足够且不过量的 vm.nr_hugepages
配少了 MySQL 启动时 fallback 到 4KB 页;配多了浪费内存、还可能挤占其他服务。关键不是“全内存”,而是覆盖 MySQL 实际申请的共享内存段:
- 主要来源是
innodb_buffer_pool_size,加上key_buffer_size、innodb_log_buffer_size、performance_schema.memory等,再上浮 10% - 假设总需求 32GB,
Hugepagesize是 2048 kB,则需vm.nr_hugepages = 32 * 1024 / 2 = 16384 - 写入
/etc/sysctl.conf:`vm.nr_hugepages = 16384`,再执行sudo sysctl -p - 验证:
cat /proc/meminfo | grep -i "hugepages_total\|hugepagesize",确保值匹配
确保 mysqld 进程能锁住并使用大页
即使内核配好了,MySQL 进程没权限也白搭。三个环节缺一不可:
-
/etc/security/limits.conf必须加两行(假设用户是mysql):mysql soft memlock unlimitedmysql hard memlock unlimited - systemd 启动时会覆盖 ulimit,检查
/usr/lib/systemd/system/mysqld.service是否含LimitMEMLOCK=infinity;没有就加,并sudo systemctl daemon-reload -
my.cnf的[mysqld]段下只写large-pages(无等号、无值、无引号),写成large-pages=ON或large_pages=1全部无效
验证是否真生效,而非假 ON
SELECT @@large_pages; 返回 1 只代表配置被读取,不代表内存已映射。必须交叉验证:
- 查进程状态:
cat /proc/$(pidof mysqld)/status | grep -i hugetlb,值 > 0 才算真用上 - 查 InnoDB 状态:
SHOW ENGINE INNODB STATUS\G,搜索Large pages used字样 - 查系统级占用:
cat /proc/meminfo | grep -i "hugepages_free",启动后应比初始值减少(减少量 ≈ buffer pool 占用页数) - 注意:
innodb_buffer_pool_size最好设为大页大小整数倍(如 2MB × N),否则余数部分仍走 4KB 页
最容易被忽略的是 systemd 的 LimitMEMLOCK 覆盖和 limits.conf 权限漏配——这两个一漏,large-pages 就是纸面功能,连 pmap 都看不到大页映射。别只盯着 my.cnf。
本文共计892个文字,预计阅读时间需要4分钟。
MySQL 在大内存服务器上启用 `large-pages` 不等同于增加一行配置即生效。多数失败案例根本原因是没有使用上大页 —— 通过 `SHOW VARIABLES LIKE 'large_pages'` 显示 `ON`,但执行 `/proc/meminfo` 里的 `HugePages_Free` 未变、在 `INNODB STATUS` 里也没有 `Large pages used`,即典型静默默认 fallback。
确认内核是否真正支持显式大页(hugetlbpage)
透明大页(transparent_hugepage)和 MySQL 要的显式大页(hugetlbpage)完全不兼容,不能混用。必须确认内核编译时启用了 CONFIG_HUGETLB_PAGE=y:
- 运行
grep -i hugetlb /boot/config-$(uname -r),有输出才表示支持;无输出就得换内核或重编译 - 再看
cat /proc/meminfo | grep -i huge:如果Hugepagesize是空或报错,说明底层未启用;HugePages_Total: 0只是还没分配,不算问题 - 别信
echo 1024 > /proc/sys/vm/nr_hugepages成功就完事——若HugePages_Free不变,大概率是物理内存不连续,尤其在长期运行的生产机上;最稳做法是重启后立刻配
计算并分配足够且不过量的 vm.nr_hugepages
配少了 MySQL 启动时 fallback 到 4KB 页;配多了浪费内存、还可能挤占其他服务。关键不是“全内存”,而是覆盖 MySQL 实际申请的共享内存段:
- 主要来源是
innodb_buffer_pool_size,加上key_buffer_size、innodb_log_buffer_size、performance_schema.memory等,再上浮 10% - 假设总需求 32GB,
Hugepagesize是 2048 kB,则需vm.nr_hugepages = 32 * 1024 / 2 = 16384 - 写入
/etc/sysctl.conf:`vm.nr_hugepages = 16384`,再执行sudo sysctl -p - 验证:
cat /proc/meminfo | grep -i "hugepages_total\|hugepagesize",确保值匹配
确保 mysqld 进程能锁住并使用大页
即使内核配好了,MySQL 进程没权限也白搭。三个环节缺一不可:
-
/etc/security/limits.conf必须加两行(假设用户是mysql):mysql soft memlock unlimitedmysql hard memlock unlimited - systemd 启动时会覆盖 ulimit,检查
/usr/lib/systemd/system/mysqld.service是否含LimitMEMLOCK=infinity;没有就加,并sudo systemctl daemon-reload -
my.cnf的[mysqld]段下只写large-pages(无等号、无值、无引号),写成large-pages=ON或large_pages=1全部无效
验证是否真生效,而非假 ON
SELECT @@large_pages; 返回 1 只代表配置被读取,不代表内存已映射。必须交叉验证:
- 查进程状态:
cat /proc/$(pidof mysqld)/status | grep -i hugetlb,值 > 0 才算真用上 - 查 InnoDB 状态:
SHOW ENGINE INNODB STATUS\G,搜索Large pages used字样 - 查系统级占用:
cat /proc/meminfo | grep -i "hugepages_free",启动后应比初始值减少(减少量 ≈ buffer pool 占用页数) - 注意:
innodb_buffer_pool_size最好设为大页大小整数倍(如 2MB × N),否则余数部分仍走 4KB 页
最容易被忽略的是 systemd 的 LimitMEMLOCK 覆盖和 limits.conf 权限漏配——这两个一漏,large-pages 就是纸面功能,连 pmap 都看不到大页映射。别只盯着 my.cnf。

