MySQL OOM(内存溢出)的解决思路

OOM全称"Out Of Memory",即内存溢出。

内存溢出已经是软件开发历史上存在了近40年的“老大难”问题。在操作系统上运行各种软件时,软件所需申请的内存远远超出了物理内存所承受的大小,就叫内存溢出。

内存溢出产生原因多种多样,当内存严重不足时,内核有两种选择:

  1. 直接panic
  2. 杀掉部分进程,释放一些内核。

大部分情况下,会杀掉导致OOM的进程,然后系统恢复。通常我们会添加对内存的监控报警,例如:当memory或swap使用超过90%时,触发报警通知,需要及时介入排查。

如果已经出现OOM,则可以通过dmesg命令查看,CentOS7版本以上支持 -T选项,能将时间戳转成时间格式,方便查看具体时间:

[root@localhost ~]# free -m    total  used  free  shared buffers  cachedMem:  128937  128527  409   1  166  1279-/+ buffers/cache:  127081  1855Swap:  16383  16252  131

通过日志可以看出哪些进程、占用多少内存等信息,并会Kill掉占用内存较大的进程。

内存问题的排查思路

一、操作系统内存检查

已MySQL为例,OOM后,mysqld进程被Killed,内存会被释放。mysqld_safe安全进程会将mysqld拉起,此时查看到的系统内存会是一个正常值。如果内存使用很高,但还未OOM,系统内存使用情况可能为下面情况:

[root@localhost ~]# free -m    total  used  free  shared buffers  cachedMem:  128937  128527  409   1  166  1279-/+ buffers/cache:  127081  1855Swap:  16383  16252  131

可以看出此时的内存使用已经很高了,物理内存和swap虚拟内存几乎都被用完,buffers和cached也不多,随时可能出现OOM的情况。

首先,通过top命名查看占用内存最大的进程:

shift+o可以选择排序方式,n代表%MEM。

[root@localhost ~]# topMem: 132031556k total, 131418864k used, 612692k free, 212104k buffersSwap: 16777212k total,  0k used, 16777212k free, 14648144k cached
 PID USER  PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND14920 mysql  20 0 125g 109g 6164 S 6.6 87.0 27357:08 mysqld 

可以看出mysqld进程占用内存最大,也可以这样查:

[root@localhost ~]# ps -e -o 'pid,comm,args,pcpu,rsz,vsz,stime,user,uid' | grep -E 'PID|mysql' |grep -v grep PID COMMAND   COMMAND      %CPU RSZ VSZ STIME USER  UID25339 mysqld   /export/servers/mysql/bin/m 9.4 115001324 130738976 2017 mysql 50032070 mysqld_safe  /bin/sh /export/servers/mys 0.0 296 106308 2017 root   0

RSZ为进程占用私有内存大小,单位Kb。
VSZ为映射的虚拟内存大小,单位Kb。

通过RSZ/total 也可以算出占用总内存比例。

二、查看给mysql分配的内存

mysql内部主要内存可通过下面语句查出:

MYSQL >SET @giga_bytes = 1024*1024*1024;SELECT (@@key_buffer_size + @@query_cache_size + @@tmp_table_size + @@innodb_buffer_pool_size + @@innodb_additional_mem_pool_size + @@innodb_log_buffer_size + (select count(HOST) from information_schema.processlist)/*@@max_connections*/*(@@read_buffer_size + @@read_rnd_buffer_size + @@sort_buffer_size + @@join_buffer_size + @@binlog_cache_size + @@thread_stack)) / @giga_bytes AS MAX_MEMORY_GB;

每个参数配置大小:

*************************** 1. row ***************************    @@key_buffer_size: 67108864    @@query_cache_size: 0     @@tmp_table_size: 268435456  @@innodb_buffer_pool_size: 38654705664@@innodb_additional_mem_pool_size: 134217728   @@innodb_log_buffer_size: 8388608    @@max_connections: 3000    @@read_buffer_size: 4194304   @@read_rnd_buffer_size: 4194304    @@sort_buffer_size: 2097152    @@join_buffer_size: 2097152    @@binlog_cache_size: 32768     @@thread_stack: 262144

每个参数配置说明:

innodb_buffer_pool_size 占用内存最大的参数 innodb_additional_mem_pool_size 额外内存,mysql5.7以后移除 innodb_log_buffer_size 重做日志缓存大小 key_buffer_size 只用于MyISAM引擎,不需要太大 tmp_table_size‍ 临时表缓存大小 query_cache_size 查询缓存,建议关闭 max_connections 最大连接数 read_buffer_size read_rnd_buffer_size sort_buffer_size join_buffer_size binlog_cache_size thread_stack 这些参数都跟线程有关,所占内存为这些参数的和*最大连接数。连接数越多占用内存也就越多,建议不超过512K,binlog_cache_size采用系统默认32K,thread_stack默认256K即可

MySQL OOM(内存溢出)的解决思路

扫一扫手机访问