mysql 8.0 core dump需同时启用core-file参数并确认innodb_buffer_pool_in_core_file与madv_dontdump支持性,否则无法生成有效core文件;还需配置ulimit和kernel.core_pattern确保系统层允许写入。

MySQL进程崩溃时,coredump 是唯一能还原崩溃瞬间内存状态的证据。但默认情况下,MySQL 8.0 不会生成完整可用的 core 文件——不是系统禁用,而是 MySQL 自身做了两层过滤:一是靠 core_file 变量开关控制是否写入,二是靠 innodb_buffer_pool_in_core_file 控制是否包含缓冲池数据。这两者必须协同配置,否则你看到的可能是空文件、被截断的文件,或根本没生成。
确认并启用 MySQL 的 core_file 参数
MySQL 的 core_file 是启动时读取的全局变量(不可动态修改),它决定 mysqld 进程收到 SIGSEGV 等信号后是否尝试写 core。即使系统 ulimit 允许,若此参数为 OFF,内核连调用 madvise(MADV_DONTDUMP) 的机会都没有,直接跳过 dump 流程。
- 检查当前值:
SELECT @@global.core_file;—— 返回OFF即未启用 - 启用方式:在
my.cnf的[mysqld]段添加core-file(注意无等号,是布尔开关) - 重启生效:
sudo systemctl restart mysql;重启后验证SHOW VARIABLES LIKE 'core_file'; - ⚠️ 常见坑:拼错成
core_file=ON或加引号,MySQL 会静默忽略该行,不报错也不生效
控制 buffer pool 是否写入 core 文件
MySQL 8.0.14+ 引入 innodb_buffer_pool_in_core_file,默认为 ON。但大型 buffer pool(比如 32GB)会导致 core 文件达数十 GB,写入慢、占磁盘、传输难。生产环境通常要关掉它,但关闭前必须确认系统支持 MADV_DONTDUMP。
- 临时关闭(需 SUPER 权限):
SET GLOBAL innodb_buffer_pool_in_core_file = OFF; - 永久关闭:在
my.cnf中添加innodb_buffer_pool_in_core_file = OFF - 验证支持性:
grep -i madv_dontdump /usr/include/asm-generic/mman.h—— 若无输出,说明内核头文件未定义,可能触发 fallback 行为 - ⚠️ 关键现象:若关闭该参数但系统不支持
MADV_DONTDUMP,MySQL 错误日志会出现警告,并自动将core_file设为 OFF —— 此时你以为关了 buffer pool,实际连 core 都不写了
确保 Linux 层面允许并定位 core 文件
MySQL 写 core 的前提是操作系统“放行”。仅配 MySQL 参数不够,还要打通 ulimit 和 sysctl 两条链路。
-
ulimit -c必须非零:MySQL 启动 shell(如 systemd service 的 ExecStart 前环境)中需设为unlimited或足够大值。systemd 用户需在 service 文件里加LimitCORE=infinity -
kernel.core_pattern要指向可写路径:比如/var/crash/core-mysqld-%p-%t;记得mkdir -p /var/crash && chmod 755 /var/crash - 验证是否生效:
cat /proc/sys/kernel/core_pattern;再看ls -l /proc/$(pgrep mysqld)/limits | grep core,确认 Max core file size 不为 0 - ⚠️ 容器场景:Docker/K8s 默认禁止 core dump,需加
--ulimit core=-1:-1和securityContext: { privileged: true }(或更细粒度的cap_add: [SYS_PTRACE])
验证与调试:拿到 core 后别急着用 gdb
MySQL 的 core 文件体积大、符号多,gdb 加载慢且容易卡死。先做三件事再调试:
- 确认 core 真实存在且非空:
file /var/crash/core-mysqld-1234-*应输出 “ELF 64-bit LSB core file x86-64” - 匹配二进制版本:
readelf -n /var/crash/core-* | grep -A2 "NT_FILE"查看崩溃时加载的 mysqld 路径,确保你用的是同一个mysqld二进制(含调试符号) - 快速回溯:用
gdb /usr/sbin/mysqld /var/crash/core-mysqld-1234-*启动后,立刻执行bt—— 若显示#0 0x0000... in ?? (),说明缺失调试信息;需重装带-g的 debuginfo 包或用objcopy --add-gnu-debuglink关联符号 - ⚠️ 最易忽略的一点:MySQL 崩溃常伴随
dmesg | grep -i "segfault.*mysqld"输出,里面含精确的 RIP 地址和 faulting instruction,比 gdb 的 bt 更早一步锁定模块问题(比如第三方 UDF 或插件)











