mysql错误日志不记录oom事件,因进程被内核oom-killer直接终止,日志仅留崩溃前模糊痕迹;可靠证据需查dmesg和系统日志,并结合performance_schema定位内存占用大户及备份场景下的叠加风险。

MySQL错误日志本身**不记录OOM事件**,翻 mysqld.err 搜索 Out of memory 或 OOM 几乎必然空手而归——因为进程是被系统 oom-killer 直接杀掉的,MySQL来不及写日志就已终止。
为什么在mysqld.err里找不到OOM线索
MySQL不会抛 OutOfMemoryError,也不会主动记录“内存溢出”。它只会在 malloc 失败时记一条模糊的 Cannot allocate memory,甚至可能完全静默。真正可靠的 OOM 证据藏在系统层,而非 MySQL 自身日志。
-
mysqld.err停在崩溃前几秒,内容常与 OOM 无关(比如最后一条是慢查询日志或连接关闭) - 物理内存耗尽触发的是内核行为,
oom-killer属于 Linux 内存管理机制,MySQL 无权也无能力记录该决策过程 - 若备份期间崩溃,
mysqldump或xtrabackup进程自身不分配大量内存,但会间接推高mysqld的缓冲压力(如激增临时表、刷脏页),最终由系统判定并出手
dmesg 和 /var/log/messages 才是第一现场
必须立刻检查系统日志,确认是否真被 oom-killer 终止,这是排查起点。
- 运行
dmesg -T | grep -i "killed process",输出中若含mysqld和时间戳,且与你观察到的崩溃时间吻合,就是铁证 - 查
/var/log/messages或/var/log/syslog,搜索oom_kill、badness、Out of memory,注意匹配时间戳 - 若没找到这些关键词,别硬调 MySQL 参数——可能是磁盘满、SELinux 拦截、或 systemd 服务超时自动重启
performance_schema 能告诉你“谁吃掉了内存”
配置没问题不代表运行时安全。用 performance_schema 查实时内存分布,定位隐性大户。
- 执行:
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、sql、memory/heap三块:若sql模块异常高,说明大量排序或临时表;若innodb占比超 85%,且Innodb_buffer_pool_wait_free > 0,说明 buffer pool 已卡死 - 检查
performance_schema自身开销:若开了全量memory/%instrument,memory/sql/sp_head::main_mem_root可能单点吃掉几 GB——关掉或限制即可
备份场景下最容易被忽略的叠加效应
不是所有备份都一样,不同方式放大内存压力的路径不同,容易误判根源。
-
mysqldump --single-transaction:依赖innodb_buffer_pool_size+ 每个连接的sort_buffer_size,大表 + 高max_connections= 叠 buff -
mysqldump --tab或SELECT INTO OUTFILE:绕过网络层,但猛增read_buffer_size和临时文件缓存,tmp_table_size设太大时,一个GROUP BY就崩 -
xtrabackup --stream=xbstream:不走 SQL 层,但触发 InnoDB 后台线程高频刷脏页,若innodb_buffer_pool_size已逼近MemAvailable,Innodb_buffer_pool_wait_free > 0是明确信号
真正危险的从来不是单个参数,而是 innodb_buffer_pool_size + max_connections × sort_buffer_size + performance_schema 开销 + 备份脚本自身内存占用的叠加。盯住 cat /proc/meminfo | grep MemAvailable,所有 MySQL 配置加起来必须小于这个值减去 2–4GB(OS、agent、backup 进程预留)。











