确认 mysqld 被 OOM Killer 杀死的铁证是 dmesg -T 输出中含“Killed process xxx (mysqld)”及 anon-rss 内存快照,时间需与 systemctl status mysqld 崩溃时间对齐;error log 不会记录 OOM,/var/log/messages 可作补充验证。

确认 mysqld 确实是被 OOM Killer 杀的
别急着改配置,先找铁证。MySQL 崩溃后 error log 里几乎不会出现 Out of memory 或 OOM 字样——因为进程是被内核直接干掉的,根本没机会写。
唯一可信来源是内核日志:dmesg -T | grep -i "killed process"。如果输出含 Killed process 12345 (mysqld) 和 total-vm:...kB, anon-rss:...kB,基本坐实。
注意时间对齐:systemctl status mysqld 显示的“Active: failed”时间,要和 dmesg 那行时间戳差在 1 分钟内;否则可能只是巧合。
补充查法(尤其 CentOS 7+):egrep -i "oom-killer|Out of memory" /var/log/messages*,有些系统会把 OOM 日志落盘到 messages 而非仅 dmesg 缓冲区。
看懂 dmesg 里的内存快照信息
dmesg 输出的 OOM 条目不是摘要,而是带内存分布的诊断快照。关键字段包括:
-
total-vm:进程虚拟内存总量(含 mmap、未分配页) -
anon-rss:真正驻留物理内存的匿名页(堆、栈、buffer pool 实际占用) -
file-rss:文件缓存映射页(如 ibd 文件 mmap 占用,通常不计入 OOM 判定主因) -
pgtables_bytes:页表开销,超 1GB 可能是大量小连接或碎片导致
若 anon-rss 远超你设的 innodb_buffer_pool_size,说明还有其他内存大户:比如 performance_schema 全量 instrument、tmp_table_size + sort_buffer_size × max_connections 的叠加效应。
查 MySQL 当前真实内存分布
配置是静态的,运行时内存怎么分才是关键。用 performance_schema 查实时占用:
Zynq‑7000 / Zynq UltraScale+ 硬件调试技能。适用于 Xilinx Zynq(Cortex‑A9/A53 + FPGA)Linux 环境,调试 I2C、I2S、UART、GPIO 等外设。包括设备树配置、内核驱动、用户空间调试工具、交叉编译和常见问题排查,支持 PetaLinux 开发。
SELECT SUBSTRING_INDEX(event_name,'/',2) AS code_area, SUM(CURRENT_NUMBER_OF_BYTES_USED) AS used FROM performance_schema.memory_summary_global_by_event_name GROUP BY code_area ORDER BY used DESC;
重点关注三块:
-
innodb:是否远超innodb_buffer_pool_size?可能是 buffer pool resize 中未完成,或 log buffer、change buffer 吃得比预期多 -
sql:高并发下 SQL 解析、执行计划缓存、临时表等消耗大 -
memory/heap:存储过程、触发器、用户变量等堆内存,容易被忽略
若 performance_schema 自身占了 1–2GB,且你不用它深度分析,可关:在 my.cnf 加 performance_schema = OFF(需重启)。
为什么调小 innodb_buffer_pool_size 还是 OOM
innodb_buffer_pool_size 是大头,但不是全部。真凶常藏在这几处:
-
table_open_cache×table_open_cache_instances:每个 instance 都缓存一份表结构,设成 16 且有几百张表 → 内存翻倍 -
tmp_table_size和max_heap_table_size取小值,设 512M + 复杂 GROUP BY 查询多 → 单查询就占几百 MB -
sort_buffer_size、join_buffer_size是 per-connection,设 4M × 500 连接 = 2GB+ -
performance-schema-instrument = 'memory/% = COUNTED':全开内存监控会让memory/sql/sp_head::main_mem_root单项吃掉几 GB
查当前连接数:SHOW GLOBAL STATUS LIKE 'Threads_connected';,再结合各缓冲参数算理论峰值,往往比 innodb_buffer_pool_size 还高。
真正该盯的不是 free -h 的 MemTotal,而是 cat /proc/meminfo | grep MemAvailable ——云主机上这个值才反映内核当前能立刻分配的内存。

















