Chinaunix首页 | 论坛 | 博客
  • 博客访问: 273121
  • 博文数量: 52
  • 博客积分: 120
  • 博客等级: 民兵
  • 技术积分: 1189
  • 用 户 组: 普通用户
  • 注册时间: 2011-08-03 15:41
个人简介

MySQL DBA

文章分类

全部博文(52)

文章存档

2013年(51)

2011年(1)

分类: Mysql/postgreSQL

2013-03-27 15:58:54

    最近新服务上线遇到一个问题:mysql 因为内存分配问题被内核干掉。

问题处理过程:

1.       查看系统资源情况。

a)         系统为多服务共存:mysql,python service ,redis 等,内存占用70%cpu 占用小于50%

b)         禁用了swap

2.       问题追踪

a)         分析syslogmysql 错误日志。Mysql kill掉的时间为00:00:20,原因为内存不足,由oom killer 停止mysql进程。

  1. Mar 26 00:00:20 AY1301300558264084667 kernel: [4687241.322857] Out of memory: Kill process 6726 (mysqld) score 96 or sacrifice child
  2. Mar 26 00:00:20 AY1301300558264084667 kernel: [4687241.322922] Killed process 6726 (mysqld) total-vm:1673084kB, anon-rss:147984kB, file-rss:0kB
  3. Mar 26 00:00:20 AY1301300558264084667 kernel: [4687241.947815] python invoked oom-killer: gfp_mask=0x201da, order=0, oom_adj=0, oom_score_adj=0
  4. Mar 26 00:00:20 AY1301300558264084667 kernel: [4687241.947819] python cpuset=/ mems_allowed=0
  5. Mar 26 00:00:20 AY1301300558264084667 kernel: [4687241.947822] Pid: 25708, comm: python Not tainted 3.2.0-29-generic #46-Ubuntu

b)         查看监控性能图,发现0点时系统load值较高,之后有一个内存释放的点(mysqldkill)。

3.       原因分析

a)         Oom killer ptython发起,且当时load值较高,初步分析由0点的crontab 任务运行时造成系统内存耗尽。

b)         分析mysql的内存使用,配置的mysql 内存上限为总物理内存的40%,由于刚上线,目前占用10%左右,连接数正常,排除mysql 内存突然增加的情况。

c)         分析mysql 中临时表的使用,发现有部分逻辑使用了临时表,且type=memory,需进一步优化。

4.       解决办法

a)         规划各程序的内存分配,控制各程序的总内存使用上限,避免内存耗尽。

b)         消除程序中数据集较大的临时表(memory),采用myisam表替代。

c)         降低crontab中任务的优先级,避免定时任务带来资源竞争。

d)         调整mysqloom_score值(保留措施)

 

Linux 内存管理 

     简单说,程序在一般情况下总是能获取到其申请的内存空间,当物理内存不足时,系统会使用swap来交换部分内存数据以维持内存开销,如果swap也耗尽,内核中的OOM killer 便会按照其算法选择并kill掉若干(一般是1个)进程以释放内存空间。

    oom killer 工作原理

    oom killer首先对正在运行的所有程序进行评分(oom_badness()),根据这个评分决定哪一个或几个程序会被kill掉。评分指标:

memory consumption #内存消耗

process ownership #进程的宿主

process age (older kenerls only) #运行时间

CPU time used (older kernels only)#cpu 使用周期

process nice value (older kernels only)#优先级

process flags #进程状态

oom_adj/oom_score_adj setting #oom 配置

    oom killer在决策过程中的考虑:

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)

而对于一个数据库服务器来说,mysql 占用的内存一般是最高的,如果用户或者其他应用程序以较高的优先级使用内存,在内存耗尽时mysqloom killer kill掉的概率是最大的。
可以从下面几个方面去避免这样的情况发生:

    1.       内存分配

    对于db和应用程序共用服务器的情况,需要对内存有一个明确的分配管理,以避免内存竞争,保证正常情况下不会有内存耗尽从而进程被oom-killer干掉的情况发生。

    2.       db buffer的配置

         mysql 使用的总内存是可控的(大量的连接以及临时表的情况除外),影响mysql内存占用的相关配置:

    主bufferMyisamkey_buffer_size,innodb_buffer_pool

    线程独享buffer,如read_buffer_size  sort_buffer_size,如果max_connection 设置的比较大,短时间的大量连接同样会占用大量的内存然后导致内存耗尽。

    临时表的配置,参加另一篇博客。临时表往往会导致内存的大量消耗。

    存储引擎的专用内存配置,如innodblog buffersizeinnodb_dict_size_limit,如果innnodb表特别多,innodb 元数据占用空间也会很大。

        Mysql 内存计算公式:


  1.         @@key_buffer_size + @@query_cache_size + @@tmp_table_size
  2.         + @innodb_buffer_pool_size + @innodb_additional_mem_pool_size
  3.         + @innodb_log_buffer_size
  4.         + @@max_connections * (
  5.         @@read_buffer_size + @@read_rnd_buffer_size + @@sort_buffer_size
  6.         + @@join_buffer_size + @@binlog_cache_size + @thread_stack
  7.         ) 

    3.       crontab脚本以及临时任务

         一般我们的统计计算脚本或者备份脚本会在凌晨运行,这些脚本会读取大量的数据到内存中,也可能造成内存的竞争,可降低其优先级。

    4.       oom killer 配置

         除了对db和应用的内存占用控制外,也可以修改oom killer 配置来干涩其决策。

    查看当前mysql oom_score值:

  1.         xchliu@AY1301300558264084667:/etc/cron.d$ cat /proc/$(pidof mysqld)/oom_score
  2.         110

    当前配置mysql的值:

  1.         xchliu@AY1211280808464774829:~$ cat /proc/$(pidof mysqld)/oom_score_adj
  2.         0

    修改配置:

  1.         xchliu@AY1301300558264084667:~$ echo '-20' > /proc/$(pidof mysqld)/oom_score_adj

5.       overcommit 优化,内存过度使用的配置。

  1.         xchliu@AY1301300558264084667:~$ ls -l /proc/sys/vm/overcommit_*
  2.         -rw-r--r-- 1 root root 0 Mar 27 13:52 /proc/sys/vm/overcommit_memory
  3.         -rw-r--r-- 1 root root 0 Mar 27 13:52 /proc/sys/vm/overcommit_ratio

overcommit_memory  接受的值:

    0 – The default value. Linux kernel uses predefined heuristics when deciding whether to allow memory overcommit or not.

    1 – Always allow overcommit. Back to the past when Linux was doing it by default.

    2 – Prevents overcommit when certain limit is exceeded.

    如果overcommit_ratio=20,而系统的swap=1G,物理内存为2G,那么系统最高可分配2G+1G*20%=2.2G的内存。


    作为db 服务器,数据库的稳定性是最重要的,Mysql oom killer 干掉的情况也是我们最不想看到,要避免这样的情况的发生,一方面要对系统的内存有清晰的分配策略;
另一方面,对于
mysql本身需要配置适当的内存。对于多个服务共存的情况,系统资源的竞争不仅是在内存上面,cpuionet 都会出现,解决的思路为:合理规划,优化个体。

 

参考:

linux 内存管理:

oom killer 工作原理:

 

阅读(9483) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~