swap空间不足导致mysql被OOM kill案例

背景:

某机器内存256G,安装2实例mysql,每个 buffer_pool106G,总计212G

某套DB晚上10:00左右迁移到该环境,第2天早上10:00左右收到OOM kill短信,因swap空间不足一个Mysql实例被强制kill

该实例mysqld进程没有被彻底清除,而是变成了僵尸进程,导致后续无法重启该实例,最后重启机器才解决。

 

调查:

swap空间不足导致mysql被OOM kill案例_第1张图片

上图为oom kill后的top输出,因为该mysqld变为僵尸进程故一直没有释放内存。

mysqlBP设置为 106G,但是其RES分别达到125G119G,加起来接近机器物理内存上限,而机器swap只有7G且被消耗完毕。

至此原因已经很清晰,解决方案也很简单,将BP调小90G

注:自调整截至目前超过10天,没有再发生类似故障。

 

延伸

1 mysql内存开销

Innodb_buffer_pool_size定义了缓存池的大小,但是缓冲池本身需要额外的数据结构进行管理。

比如,缓冲池每个page都需要一个buf_block_t管理,这部分内存没有计入参数。

各种额外消耗加起来约占整个BP8%,也有资料说是10%,具体可参看http://mysqlha.blogspot.co.uk/2008/11/innodb-memory-overhead.html

这些只是global buffer的开销,加上session bufferMysql所需的内存只会更高。

 

 

2 为什么会发生swap

首先大致说一下linux的内存管理,numa架构下linux内存被分为多个node,非numa则只有1个,由pg_data_t描述,每个node又分为3zone,由zone_struct结构体描述。

每个zone都有active_lru inactive_lru,每个lru又各分为anon匿名页和file cache映射页链表,总计4LRU

zone同时定义了pages_lowpages_minpages_high,当zone可用内存小于pages_low时唤醒kswapd回收内存,而当其小于pages_min时则以同步方式唤醒kswapd,直到zone可用内存达到pages_high为止;

Linux会缓存很多数据,譬如page cacheslab cache,这部分内存在回收时会先同步到磁盘然后直接重用,而对于其他内存页,诸如用户态地址空间的匿名页,以及IPC共享内存区的页,只能将其置换到swap分区,不可直接回收。

 

 

OS何时回收内存?

1 定期回收:kswapd定期唤醒,当zone空闲内存小于pages_low则进行页面回收,小于pages_min则以同步方式回收;

2 直接回收:linux为用户进程分配内存或者创建缓冲区,而当前系统又没有足够多物理内存时,则linux会进行页面回收;当OS尝试内存回收后仍无法获取足够多的页面,则调用find_bad_process并进行OOM kill

swap空间不足导致mysql被OOM kill案例_第2张图片

 

不管哪种回收方式,最后都调用shrink_list(),对4个链表的扫描逻辑定义在vmscan.c中的get_scan_count函数内,其变量scan_balance决定了要回收哪个lru的内存,大致逻辑如下:

1. 如果系统禁用了swap或者没有swap空间,则只扫描file based的链表,即不进行匿名页链表扫描

       if (!sc->may_swap || (get_nr_swap_pages() <= 0)) {

                scan_balance = SCAN_FILE;

                goto out;

        }

 

2. 如果当前进行的不是全局页回收,并且swappiness=0,则不进行匿名页链表扫描

        if (!global_reclaim(sc) && !vmscan_swappiness(sc)) {

                scan_balance = SCAN_FILE;

                goto out;

        }

 

3. 如果是全局页回收,并且空闲内存和file based链表page数目相加都小于zone->pages_high,则进行匿名页回收,即便swappiness=0,系统也会进行swap

         if (global_reclaim(sc)) {

                   unsigned long zonefile;

                   unsigned long zonefree;

 

                   zonefree = zone_page_state(zone, NR_FREE_PAGES);

                   zonefile = zone_page_state(zone, NR_ACTIVE_FILE) +

                               zone_page_state(zone, NR_INACTIVE_FILE);

 

                   if (unlikely(zonefile + zonefree <= high_wmark_pages(zone))) {

                            scan_balance = SCAN_ANON;

                            goto out;

                   }

         }

 

4. 如果系统inactive file链表比较充足,则不考虑进行匿名页的回收,即不进行swap

         if (!inactive_file_is_low(lruvec)) {

                   scan_balance = SCAN_FILE;

                   goto out;

         }

 

至此,我们可以大致了解swappiness=0的作用,其并不能完全禁止swap

 

 

何时触发OOM kill

当系统内存被消耗殆尽,swap分区也被填满的时候,内核无法分配到新的空闲内存,便会启动OOM删除程序;

其内核调用路径为out_of_memory() – select_bad_process() – oom_kill_process()

其中select_bad_process()负责挑选待杀死的进程,其扫描系统中的每一个进程并调用oom_badness(),该API逻辑如下:

1 获取进程的oom_score_adj,如果其等于OOM_SCORE_ADJ_MIN-1000则不Kill,该参数由/proc/NNN/ oom_score_adj记录,可手工修改

         adj = (long)p->signal->oom_score_adj;

         if (adj == OOM_SCORE_ADJ_MIN) {

                   task_unlock(p);

                   return 0;

         }

 

2 根据该进程消耗的内存计算分数,如果是root进程则乘以3%,尽量避免其被Kill,最后将points返回

         points = get_mm_rss(p->mm) + get_mm_counter(p->mm, MM_SWAPENTS) +

                   atomic_long_read(&p->mm->nr_ptes) + mm_nr_pmds(p->mm);

         task_unlock(p);

 

         if (has_capability_noaudit(p, CAP_SYS_ADMIN))

                   points -= (points * 3) / 100;

 

select_bad_process()通过比较每一个进程的oom_badness()返回值,找出得分最高且不是线程组leader的进程,将其返回给out_of_memory(),由其调用oom_kill_process()发送sigkill信号进行扑杀。

 

除了杀死进程,Linux可以选择在发生OOM时直接panic,当vm.panic_on_oom=1时成立

 

 

结束语

至此我们可以大致了解swappiness=0的意义,以及OOM kill发生的原因,为避免此行为应尽量留出充足的内存给OS,一般应为物理内存的20%左右。

 

参考资料

http://www.ibm.com/developerworks/cn/linux/l-cn-pagerecycle/index.html?ca=dat

http://www.douban.com/note/349467816/

https://github.com/torvalds/linux/blob/master/mm/oom_kill.c

 

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/15480802/viewspace-1815985/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/15480802/viewspace-1815985/

你可能感兴趣的:(数据库,运维,内存管理)