MySQL Crash 问题处理思路
(一)当发生Crash 时 error log 没有日志信息,这时候需要查看/var/log/messages
这种情况一般是发生在MySQL进程被强制杀死,发生在下列的两种情形之一:1. kill -9命令
如果是被kill-9强制杀死的,/var/log/messages会有类似如下输出内容:
May11 06:10:44 localhost systemd: mysqld_3306.service: main process exited, code=killed, status=9/KILL2. OOM
如果是发生了OOM,/var/log/messages会有类似如下输出内容:
Out of memory: Kill process9682 (mysqld) score 9 orsacrifice child
Killed process9682, UID 27, (mysqld) total-vm:47388kB, anon-rss:3744kB, file-rss:80kB
说明:
anon-rss:3744kB 表示mysqld进程占用的真实内存,占用太高就会触发OOM。
OOM的原因通常有:
(1)MySQL内存需求加起来超出了物理内存(包括 swap)的容量,比服务器总内存(包括 swap)还大。
内核(OOM killer)必须杀掉一些进程才能腾出空间保障系统正常运行,因为MySQL在系统上占用内存最多,所以如果 Out of Memeory (OOM) 的话总是不幸第一个被 kill 掉。
解决这个问题最简单的办法就是增加内存,或者想办法优化 MySQL 使其占用更少的内存。
除了优化 MySQL 外还可以优化系统,让系统尽可能使用少的内存以便应用程序(如 MySQL) 能使用更多的内存。
还有一个临时的办法就是调整内核参数,让 MySQL 进程不容易被 OOM killer 发现。
配置 OOM killer
在触发 OOM 后立刻触发 kernel panic,kernel panic 10秒后自动重启系统#sysctl -w vm.panic_on_oom=1
vm.panic_on_oom = 1
#sysctl -w kernel.panic=10
kernel.panic = 10
#echo "vm.panic_on_oom=1" >> /etc/sysctl.conf#echo "kernel.panic=10" >> /etc/sysctl.conf
如果不想 MySQL 进程被轻易杀掉的话可以找到 MySQL 运行的进程号后,调整 oom_score_adj 为-15(注意 points 越小越不容易被杀):#ps aux | grep mysqld
mysql 2196 1.6 2.1 623800 44876 ? Ssl 09:42 0:00 /usr/sbin/mysqld#cat /proc/2196/oom_score_adj
0#echo -15 > /proc/2196/oom_score_adj
如果需要的话可以完全关闭 OOM killer(不推荐用在生产环境):#sysctl -w vm.overcommit_memory=2#echo "vm.overcommit_memory=2" >> /etc/sysctl.conf
查看MySQL里谁消耗了内存:
SELECT event_name,SUM_NUMBER_OF_BYTES_ALLOC FROM
performance_schema.memory_summary_global_by_event_name
ORDER BY SUM_NUMBER_OF_BYTES_ALLOC DESC LIMIT10;
查看MySQL里哪些内部线程消耗了内存:
select event_name, SUM_NUMBER_OF_BYTES_ALLOCfromperformance_schema.memory_summary_by_thread_by_event_name
order by SUM_NUMBER_OF_BYTES_ALLOC desc limit20;
(2)MySQL发生了内存泄漏。
物理内存还有不少空闲,但却把swap都耗尽了,绝大多数情况是因为没有关闭NUMA引起的。
用free 查看,如果发现内存统计结果中,cached 和 used 相差特别大的话,基本可确定系统发生内存泄露。
(二)当发生Crash 时 error log 有日志信息
案例1
Semaphore wait has lasted> 600seconds. We intentionally crash the server because it appears to be hung.
案例2
mysqld got signal11虽然error log打印了部分信息,但是对于分析原因来说往往不够,推荐开启coredump,让MySQL在crash时打印更多信息,coredump的分析非常复杂,需要阅读MySQL源码,此处不展开,只介绍开启coredump的方法。
开启方法如下:
(1)系统设置:
echo1 > /proc/sys/kernel/core_uses_pid
echo2 > /proc/sys/fs/suid_dumpable
注意 coredump 文件非常大,需要确保/tmp空间够用:
echo"/tmp/core-%e-%s-%u-%g-%p-%t" > /proc/sys/kernel/core_pattern
调整 MySQL 运行用户的 ulimit,调整其 core file 的限制,使其能生成 core dump:
ulimit-c unlimited
ulimit-a |grep core 显示 unlimited 即可
(2)修改MySQL配置并重启
echo"core-file" >> my.cnf