数据库性能不稳、延迟抖动或节点异常重启,大概率因THP未真正关闭;必须同时将enabled和defrag设为[never],并配置内核参数transparent_hugepage=never,再重启数据库进程验证。

数据库在 Linux 上性能不稳、延迟抖动、甚至节点异常重启,大概率是透明大页(THP)没真正关掉——只改 /sys/kernel/mm/transparent_hugepage/enabled 是无效的,defrag 和内核参数必须同步设为 never,否则 khugepaged 线程照常扫描、合并、拆分内存,卡顿就藏在后台。
为什么只写 enabled=never 不算关闭 THP
THP 实际生效由两个开关共同控制:enabled 决定是否允许分配大页,defrag 控制是否允许内核后台线程 khugepaged 主动扫描并合并小页。即使 enabled 是 [never],只要 defrag 是 [always] 或 [defer+madvise],khugepaged 就会周期性唤醒,触发内存迁移、页面拆分和锁竞争,导致数据库短时卡顿、major-faults 上升、RAC 节点失联。
验证方式必须两条都查:
-
cat /sys/kernel/mm/transparent_hugepage/enabled输出中[never]在方括号里 -
cat /sys/kernel/mm/transparent_hugepage/defrag输出中[never]也在方括号里
常见误判:输出为 always [madvise] never —— 这表示当前生效的是 madvise,仍属启用状态。
临时禁用 THP(调试/压测用)
立刻生效但重启失效,适合快速验证问题是否由 THP 引起。注意:两条命令缺一不可,且顺序无关:
echo never > /sys/kernel/mm/transparent_hugepage/enabledecho never > /sys/kernel/mm/transparent_hugepage/defrag
执行后立即用上面两个 cat 命令确认,两行都显示 [never] 才算成功。此时 khugepaged 线程会停止活动,AnonHugePages 在 /proc/meminfo 中应趋近于 0。
Linux 安全审计工具,检查 SSH 配置、开放/监听端口、防火墙规则(ufw/iptables/nftables)、失败登录尝试、sudoers 权限...
永久禁用 THP(生产环境唯一可靠方式)
/etc/rc.local 或 systemd service 容易被 tuned、cloud-init、systemd-sysctl 覆盖,尤其在 RAC、容器或云主机中极不可靠。最优先级最高、最彻底的方式是通过内核启动参数:
- 编辑
/etc/default/grub,在GRUB_CMDLINE_LINUX行末尾追加:transparent_hugepage=never - 执行
grub2-mkconfig -o /boot/grub2/grub.cfg(BIOS)或/boot/efi/EFI/redhat/grub.cfg(UEFI) reboot
该参数会强制覆盖所有运行时设置,包括 enabled 和 defrag 的值,且不依赖任何用户空间服务。重启后检查 cat /proc/cmdline 是否含 transparent_hugepage=never,再跑两个 cat 命令确认双 [never]。
禁用后必须重启数据库进程
改完内核参数 ≠ 数据库进程已脱离 THP 影响。Oracle、MySQL、PostgreSQL 等在启动时可能已申请过 THP 映射,后续不会自动释放。不重启,AnonHugePages 可能长期非零,perf stat -e major-faults -p $(pgrep -f mysqld) 仍会看到高值。
具体操作因数据库而异:
- Oracle 单机:重启
dbstart或sqlplus / as sysdba执行shutdown immediate; startup; - Oracle RAC:必须重启整个 CRS 栈:
crsctl stop crs && crsctl start crs,仅重启 DB 实例无效 - MySQL:
systemctl restart mysqld,确认grep -i anonhugepages /proc/$(pgrep -f mysqld)/smaps | awk '{sum += $2} END {print sum}'返回 0 - Redis:官方明确要求,不重启无法消除 fork() 延迟风险
最容易被跳过的就是这一步:很多现场排查发现 enabled 和 defrag 都是 [never],但数据库进程从上次开机就没重载过内存策略,ocssd.bin 或 mysqld 仍在用 THP 映射。










