MySQL DBA
分类: Mysql/postgreSQL
2013-03-27 15:58:54
问题处理过程:
1. 查看系统资源情况。
a) 系统为多服务共存:mysql,python service ,redis 等,内存占用70%,cpu 占用小于50%。
b) 禁用了swap
2. 问题追踪
a) 分析syslog及mysql 错误日志。Mysql 被kill掉的时间为00:00:20,原因为内存不足,由oom killer 停止mysql进程。
b) 查看监控性能图,发现0点时系统load值较高,之后有一个内存释放的点(mysqld被kill)。
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) 调整mysql的oom_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 占用的内存一般是最高的,如果用户或者其他应用程序以较高的优先级使用内存,在内存耗尽时mysql被oom killer kill掉的概率是最大的。
可以从下面几个方面去避免这样的情况发生:
1. 内存分配
对于db和应用程序共用服务器的情况,需要对内存有一个明确的分配管理,以避免内存竞争,保证正常情况下不会有内存耗尽从而进程被oom-killer干掉的情况发生。
2. db buffer的配置
mysql 使用的总内存是可控的(大量的连接以及临时表的情况除外),影响mysql内存占用的相关配置:
主buffer。Myisam的key_buffer_size,innodb_buffer_pool
线程独享buffer,如read_buffer_size 和 sort_buffer_size,如果max_connection 设置的比较大,短时间的大量连接同样会占用大量的内存然后导致内存耗尽。
临时表的配置,参加另一篇博客。临时表往往会导致内存的大量消耗。
存储引擎的专用内存配置,如innodb的log buffersize和innodb_dict_size_limit,如果innnodb表特别多,innodb 元数据占用空间也会很大。
Mysql 内存计算公式:
3. crontab脚本以及临时任务
一般我们的统计计算脚本或者备份脚本会在凌晨运行,这些脚本会读取大量的数据到内存中,也可能造成内存的竞争,可降低其优先级。
4. oom killer 配置
除了对db和应用的内存占用控制外,也可以修改oom killer 配置来干涩其决策。
查看当前mysql 的oom_score值:
当前配置mysql的值:
修改配置:
5. overcommit 优化,内存过度使用的配置。
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本身需要配置适当的内存。对于多个服务共存的情况,系统资源的竞争不仅是在内存上面,cpu、io、net 都会出现,解决的思路为:合理规划,优化个体。
参考:
linux 内存管理:
oom killer 工作原理: