MySQL OOM 系统二 OOM Killer_Mysql

这里就涉及到一个问题,到底Kill掉谁呢?一般稍微了解一些Linux内核的同学第一反应是谁用的最多,就Kill掉谁。这当然是Linux内核首先考虑的一种重要因素,但是也不完全是这样的,我们查一些Linux的内核方面的资料,可以知道其实Kill谁是由/proc/<pid>/oom_score来决定的,这个值每个进程一个,是由Linux内核的oom_badness()函数负责计算的。那下面我们来仔细读一读badness()函数。  

在badness()函数的注释部分,写明了badness()函数的处理思路:

         1) we lose the minimum amount of work done
         2) we recover a large amount of memory
         3) we don't kill anything innocent of eating tons of memory
         4) we want to kill the minimum amount of processes (one)
         5) we try to kill the process the user expects us to kill, this  algorithm has been meticulously tuned to meet the principle of least surprise ... (be careful when you change it)

总的来说就是Kill掉最小数量的进程来获取最大数量的内存,这与我们Kill掉占用内存最大的进程是吻合的。

        /*
         * The memory size of the process is the basis for the badness.
         */

         points = p->mm->total_vm;

分数的起始是进程实际使用的RAM内存,注意这里不包括SWAP,即OOM Killer只会与进程实际的物理内存有关,与Swap是没有关系的,并且我们可以看到,进程实际使用的物理内存越多,分数就越高,分数越高就越容易被牺牲掉。

        /*
         * Processes which fork a lot of child processes are likely
         * a good choice. We add the vmsize of the childs if they
         * have an own mm. This prevents forking servers to flood the
         * machine with an endless amount of childs
         */
          ...
                  if (chld->mm != p->mm && chld->mm)
                        points += chld->mm->total_vm;

这段表示子进程占用的内存都会计算到父进程上。

        s = int_sqrt(cpu_time);
        if (s)
                points /= s;
        s = int_sqrt(int_sqrt(run_time));
        if (s)
                points /= s;

 这表明进程占用的CPU时间越长或者进程运行的时间越长,分数越低,越不容易被Kill掉。

       /*
        * Niced processes are most likely less important, so double
        * their badness points.
        */
        if (task_nice(p) > 0)
                points *= 2;

          如果进程优先级低(nice值,正值低优先级,负值高优先级),则Point翻倍。

       /*
        * Superuser processes are usually more important, so we make it
        * less likely that we kill those.
        */
        if (cap_t(p->cap_effective) & CAP_TO_MASK(CAP_SYS_ADMIN) ||
                                p->uid == 0 || p->euid == 0)
                points /= 4;

          super用户的进程优先级较低。

        /*
         * We don't want to kill a process with direct hardware access.
         * Not only could that mess up the hardware, but usually users
         * tend to only have this flag set on applications they think
         * of as important.
         */
        if (cap_t(p->cap_effective) & CAP_TO_MASK(CAP_SYS_RAWIO))
                points /= 4;

          直接可以访问原始设备的进程优先级较高。

        /*
         * Adjust the score by oomkilladj.
         */
        if (p->oomkilladj) {
                if (p->oomkilladj > 0)
                        points <<= p->oomkilladj;
                else
                        points >>= -(p->oomkilladj);

        }

每个进程有个oomkilladj 可以设置该进程被kill的优先级,这个参数看上去对Point影响还是比较大的,oomkilladj 最大+15,最小是-17,越大越容易被干掉,这个值由于是移位运算,所以影响还是比较大的。

下面我写个小程序实验一下:

 #define MEGABYTE 1024*1024*1024
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
 int main(int argc, char *argv[])
{
void *myblock = NULL;
myblock = (void *) malloc(MEGABYTE);
printf("Currently allocating 1GB\n");
sleep(1);
int count = 0;
while( count < 10)
{
 memset(myblock,1,100*1024*1024);
 myblock = myblock + 100*1024*1024;
 count++;
 printf("Currently allocating %d00 MB\n",count);
 sleep(10);
  }
  exit(0);
 }

上面的程序先申请一个1G的内存空间,然后100M为单位,填充这些内存空间。在一个2G内存,400M Swap空间的机器上跑3个上面的进程。我们看一下运行结果:

   

     test1、test2、test3分别申请了1G的虚拟内存空间(VIRT),然后每隔10s,实际占用的RAM空间就增长100M(RES)。

    

    当物理内存空间不足时,OS开始进行Swap,可用的Swap空间开始减少。

   
    

     当内存是在没有可分配的空间时,test1进程被操作系统Kill掉了。dmesg 我们可以看到,test1进程被OS Kill掉,同时oom_score为1000。

     这3个进程的oom_adj全部都是默认值0。下面我们来实验一下设置了oom_adj的效果。重新启动3个进程,然后我们看到test2的PID是12640

       

   我们运行一下下面的语句

   echo 15 > /proc/12640/oom_adj

  一段时间后,我们看到Swap空间急剧减少,基本上OS OOM_Killer要开动了。 

   

     果然,不出意料,12640进程被kill掉了。

     所以为了避免自己需要的进程被kill掉,可以通过设置进程的oom_adj来实现。当然,有的人会说,这一切都是超售引起的,既然Linux提供了overcommit_memory可以禁用overcommit特性,那为什么不禁用呢。这有利也有弊,一旦禁用overcommit,就意味着MySQL根本无法申请超过实际内存的空间,而在MySQL中,存在很多动态申请内存空间的地方,如果申请不到,MySQL就会Crash,这大大增加了MySQL宕机的风险,这也是Linux为什么要overcommit的原因。

      有了上面的分析,我们不难看出,如果在不设置oom_adj的前提下,MySQL一般都会成为OOM_Killer的首选对象,因为MySQL一般都是内存的最大占用者。那作为MySQL,我们如何尽量的去规避被Kill的风险呢,下一章我们将重点从MySQL的角度分析如何规避OOM。

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索oom
Killer
oom killer、invoked oom killer、linux oom killer、oom killer 日志分析、oom killer 日志,以便于您获取更多的相关知识。

时间: 2024-09-29 03:08:34

MySQL OOM 系统二 OOM Killer_Mysql的相关文章

Linux系统的OOM Killer处理机制

  最近有位 VPS 客户抱怨 MySQL 无缘无故挂掉,还有位客户抱怨 VPS 经常死机,登陆到终端看了一下,都是常见的 Out of memory 问题.这通常是因为某时刻应用程序大量请求内存导致系统内存不足造成的,这通常会触发 Linux 内核里的 Out of Memory (OOM) killer,OOM killer 会杀掉某个进程以腾出内存留给系统用,不致于让系统立刻崩溃.如果检查相关的日志文件(/var/log/messages)就会看到下面类似的 Out of memory:

PHP+MYSQL会员系统的开发实例教程_php技巧

本文通过一个简单的实例完成了完整的PHP+MySQL会员系统功能.是非常实用的一个应用.具体实现步骤如下: 一.会员系统的原理:    登陆-->判断-->保持状态(Cookie或Session)-->验证状态及其权限 二.会员系统的安全: 1.学会使用常量提高md5安全性 2.Cookie/ Session 少用明文信息 3.Session安全性要大于Cookie 4.使用Cookie/ Session读取信息 尽量增加判断信息 5.Cookie/ Session内容要精简 6.对于错

MySQL获取系统当前时间的函数

环境:MySQL Server 5.1 问题:MySQL获取系统当前时间的函数 解决: NOW()函数以'YYYY-MM-DD HH:MM:SS'返回当前的日期时间,可以直接存到DATETIME字段中. CURDATE()以'YYYY-MM-DD'的格式返回今天的日期,可以直接存到DATE字段中. CURTIME()以'HH:MM:SS'的格式返回当前的时间,可以直接存到TIME字段中. 示例: SQL: select now() as 当前日期时间; select curdate() as 今

Win7系统二合一安装盘正确制作方法

  ghost win7的二合一安装盘制作是每一个用户需要知道的一个小技巧,该安装盘的制作方便快捷,既有利于日后的重装系统,又有利于用户的恢复,所以对用户来说意义还是很大的,接下来就向各位介绍制作的方法,而二合一安装盘制作其实就是将Windows7和WindowsXP整合在一起的一种安装盘制作方式. 1.下载ultraISO,用来提取Windows7的启动文件,通过启动和保存引导文件,让其保存为Win7.bif,并存储在光盘镜像制作软件EasyBootdisk1ezboot之中. 2.将Wind

《PHP、MySQL和Apache入门经典(第5版)》一2.8 MySQL权限系统简介

2.8 MySQL权限系统简介 PHP.MySQL和Apache入门经典(第5版) MySQL权限系统总是起作用的.当你第一次尝试连接MySQL服务器的时候,并且对于每一个后续的动作,MySQL都会检查以下3件事情. 你从哪里访问(你的主机)? 你说你是谁(你的用户名和密码)? 允许你做什么(你的命令权限)? 所有这些信息都存储在一个名为mysql的数据库中,当安装MySQL的时候,自动创建该数据库.在mysql数据库中,有如下几个和权限相关的表. columns_priv--为一个表中的具体字

oa系统二次-OA系统二次开发怎么样

问题描述 OA系统二次开发怎么样 有哪位大神做过OA系统二次开发的,OA二次开发怎么样啊,工作量大吗?难度怎么样啊?跪求指点,谢谢啦. 解决方案 我是做erp二开的,我觉得做这个对以后的成长不太好,技术上成长不太理想,不是纯开发,用的是二开平台

计算机-mysql本地系统的与网络服务有什么区别?

问题描述 mysql本地系统的与网络服务有什么区别? [MySQL5.7版本] 首先贴图如下:计算机-mysql本地系统的与网络服务有什么区别?-本地计算机的mysql"> 当登陆mysql时使用的是net start mysql57,可以正常登陆登出.而使用net start mysql却是可以的,提示如下: 当我试图手动启动mysql服务(不是mysql57)时,提示"本地计算机上的mysql服务启动后停止.某些服务在未由其他服务或程序使用时将自动".而且当用mys

ERP系统二次开发的原因

ERP实施过程中,由于各企业情况不同,必然会存在一些无法满足企业需求的情况,虽然系统通过参数调整可以满足部分需求,但很多情况下都需要改动原有程序.甚至需要修改原始数据库结构来满足需求. ERP系统二次开发的原因 1.用户不接受新系统的操作习惯 ERP产品为了保持较强的通用性,功能跟流程的设置都是标准与规范的.但在实施时,除了业务流程等方面具有个性化需求外,还存在着一些不涉及业务流程的.由企业的特殊性而产生的操作习惯需求,而提出了大量的二次开发. 2.企业不规范的管理制度造成的特殊流程需求 大部分

《PHP、MySQL和Apache入门经典(第5版)》一一2.8 MySQL权限系统简介

2.8 MySQL权限系统简介 PHP.MySQL和Apache入门经典(第5版) MySQL权限系统总是起作用的.当你第一次尝试连接MySQL服务器的时候,并且对于每一个后续的动作,MySQL都会检查以下3件事情. 你从哪里访问(你的主机)? 你说你是谁(你的用户名和密码)? 允许你做什么(你的命令权限)? 所有这些信息都存储在一个名为mysql的数据库中,当安装MySQL的时候,自动创建该数据库.在mysql数据库中,有如下几个和权限相关的表. columns_priv--为一个表中的具体字