mysql 8.0需通过systemd的environmentfile注入ld_preload加载jemalloc,因默认不走mysqld_safe,直接改其配置无效;验证须用lsof确认libjemalloc.so.2被进程加载。

MySQL 8.0 默认不走 mysqld_safe 启动,所以往 [mysqld_safe] 里加 malloc-lib 是无效的——这招只对 MySQL 5.6 及更早版本管用。
确认当前内存分配器是 glibc
先验证你确实还没切到 jemalloc:
- 查进程:运行
ps -ef | grep mysqld,看输出里有没有jemalloc或tcmalloc字样 - 查加载库:执行
lsof -Pn -p $(pidof mysqld) | grep -i malloc,如果只看到libc.so、没任何libjemalloc路径,说明还在用 glibc 的malloc - 注意架构路径差异:x86_64 通常是
/usr/lib64/libjemalloc.so.2,aarch64(如 Arm64 CentOS)可能是/usr/lib/libjemalloc.so.2或/usr/local/lib/libjemalloc.so.2,别硬套路径
安装 jemalloc 并确保能被找到
不要跳过这步直接改启动参数——很多失败源于库文件根本没装对位置或没进动态链接缓存:
- 推荐用包管理器安装(更省心):
yum install jemalloc(RHEL/CentOS)或apt install libjemalloc2(Debian/Ubuntu) - 若手动编译,务必执行
make install && ldconfig,否则ldconfig -p | grep jemalloc看不到它 - 查实际路径最可靠方式:
find /usr -name "libjemalloc.so*" 2>/dev/null或cat /usr/bin/jemalloc.sh 2>/dev/null | grep LD_PRELOAD - 别用
/usr/local/lib路径直接配 systemd——除非你已把该路径写入/etc/ld.so.conf.d/并执行了ldconfig
通过 systemd 注入 LD_PRELOAD 启动 MySQL
这是 MySQL 8.0 官方推荐且最稳定的方式,绕过所有 mysqld_safe 兼容性问题:
- 编辑 service 文件:
systemctl edit --full mysqld(或直接改/usr/lib/systemd/system/mysqld.service) - 在
[Service]段下添加:EnvironmentFile=-/etc/sysconfig/mysql(注意=-中的短横,表示文件不存在也不报错) - 创建
/etc/sysconfig/mysql,写入一行:LD_PRELOAD=/usr/lib64/libjemalloc.so.2(替换成你上一步确认的真实路径) - 重载并重启:
systemctl daemon-reload && systemctl restart mysqld - 验证是否生效:
lsof -Pn -p $(pidof mysqld) | grep jemalloc—— 必须看到类似/usr/lib64/libjemalloc.so.2的输出才算成功
为什么不用 LD_PRELOAD=xxx mysqld --daemonize 手动启动?
短期测试可以,但生产环境千万别这么干:
- systemd 会丢失进程父子关系,
systemctl status mysqld显示为 inactive,监控和自动拉起失效 - MySQL 的信号处理(如
SIGHUP重载配置)、优雅关闭(systemctl stop)可能异常 - 日志归属混乱:手动启动时
mysqld不再由 systemd 管理,journalctl -u mysqld查不到完整日志 - 如果你真试过手动启动又切回 systemd,记得先
killall mysqld再systemctl start,否则端口冲突或 PID 文件残留会导致启动失败
最关键的细节藏在路径和权限里:LD_PRELOAD 指向的 so 文件必须对 mysql 用户可读,且不能是符号链接断裂的假路径;systemd 加载 EnvironmentFile 时不会报错提示路径错误,只会静默忽略——所以验证环节缺一不可。











