设为首页 加入收藏

TOP

MySQL案例-mysqld got signal 11(二)
2016-12-08 08:15:02 】 浏览:1385
Tags:MySQL 案例 -mysqld got signal
5834871 K bytes of memory
这一段计算了当前配置下, 需要的最大内存数, 大概换算了一下, 是234G;


这么高, 明显是有问题的, 联想到82%内存使用率的报警信息, 推测是内存耗尽造成的;


用max_used_connections来算一下使用的内存的话,有约1.5G;


加上BP的9.6G, 有11G了, 算上MySQL本身占用的一部分内存, 确实达到了比较高的程度;


但是看了一下kernel和message, 都没有发现系统出现OOM的日志, 应该不是系统kill的;



再看看堆栈相关的信息, 在里面记录了MySQL crash时的状态;


stack_bottom = 7f6141b36e80 thread_stack 0x40000
/usr/sbin/mysqld(my_print_stacktrace+0x2c)[0xe77fec]
/usr/sbin/mysqld(handle_fatal_signal+0x459)[0x7a7019]
/lib/x86_64-linux-gnu/libpthread.so.0(+0xf8d0)[0x7f643257a8d0]
/usr/sbin/mysqld(_ZN16Partition_helper25handle_ordered_index_scanEPh+0x5c)[0xbbabec]
/usr/sbin/mysqld(_ZN7handler13ha_index_lastEPh+0x1b0)[0x7f4410]
/usr/sbin/mysqld(_Z14join_read_lastP7QEP_TAB+0x65)[0xc1f605]
/usr/sbin/mysqld(_Z10sub_selectP4JOINP7QEP_TABb+0x11b)[0xc25e4b]
/usr/sbin/mysqld(_ZN4JOIN4execEv+0x3b8)[0xc1ea78]
/usr/sbin/mysqld(_Z12handle_queryP3THDP3LEXP12Query_resultyy+0x238)[0xc8e408]
/usr/sbin/mysqld[0x770ccf]
/usr/sbin/mysqld(_Z21mysql_execute_commandP3THDb+0x3403)[0xc51103]
/usr/sbin/mysqld(_Z11mysql_parseP3THDP12Parser_state+0x3ad)[0xc531bd]
/usr/sbin/mysqld(_Z16dispatch_commandP3THDPK8COM_DATA19enum_server_command+0x817)[0xc53a47]
/usr/sbin/mysqld(_Z10do_commandP3THD+0x18f)[0xc54faf]
/usr/sbin/mysqld(handle_connection+0x278)[0xd108d8]
/usr/sbin/mysqld(pfs_spawn_thread+0x1b4)[0xe90784]
/lib/x86_64-linux-gnu/libpthread.so.0(+0x80a4)[0x7f64325730a4]
/lib/x86_64-linux-gnu/libc.so.6(clone+0x6d)[0x7f6430e1b87d]
从红字等地方的信息, 可以推断出当时MySQL是正在执行查询, 这些查询中有join, 也有subquery, 且查询的表包含了分区表;


可以预料到在crash的时候, MySQL执行这些语句时肯定需要申请一部分join用的buffer, 同时子查询也会建立临时表, 都需要占用内存空间;


同时还有分区表的使用, 看了一下当时候分区表的大小:



发现当天的数据超过了BP的大小, 且用到分区表的查询走的全表扫描, 并且还有order by, 会用到sort的buffer, 且由于全表扫描的数据很多, 这个buffer有可能是需要申请满的;


综合这些信息, 基本确认是内存耗尽造成了MySQL crash;


那么根据堆栈的信息尝试还原crash时的场景:


在内存占用率很高的情况下, MySQL thread在执行较大表的查询时, 无法再申请到足够的内存(sort的buffer, join的buffer等), 因此发生了crash;


处理方式:
最终把BP从9.6G调整为9G, 并把sort, read等buffer的数值调整到了4M, 其他的buffer也调低了;


PS: 算是疏忽吧, 因为说在生产环境已经用这么一套配置很久了, 没出过问题, 所以也没有仔细的排查配置文件中的设置;
PSS: sort的buffer原来是多少 32M...sort的buffer还是per thread的...失职了..._(:з」∠)_


-------------------------------------------------------------------------------------------------后续---------------------------------------------------------------------------------------------------------------


峰回路转.....在调整了buffer的数量以后, 不可能再出现内存不够的现象了, 然后crash的现象重现了;


而且是主库和备库在非常短的时间内都发生了crash;


报错信息除了pointer不同以外, 堆栈的信息也是完全一致;


包括那个语句;
在之前出问题的时候, 记录了一条语句:


select * from test where time>='2016-07-29 00:00:00' and time<='2016-07-29 23:59:59' and tag in (2,3,6) order by id desc limit 2000
在后来重现的时候, 两次crash的语句中, 记录的是同样的语句, (而且堆栈的输出信息也是完全一样) , 仅仅只是时间不一样:


select * from test where time>='2016-08-09 00:00:00' and time<='2016-08-09 23:59:59' and tag in (2,3,6) order by id desc limit 2000
如果是因为内存or系统资源的不可用导致了crash的话, 不可能有这么巧合的事情, 都是这个语句;


so, 在被拉起来的备库上跑了一下这个语句, 结果MySQL马上就crash了...



那么明显就是这个语句的问题了, order by desc + limit, 看上去并没什么问题, 看看explain的结果



虽然好久没做开发了, 但是filtered在100%的情况下, rows只有1还是挺奇怪的, 一整张表只有一行数据, 但是还有这种查询一整天的语句;


看看表的结构;
隐去生产库上的一部分信息, 留下关键的部分;




分区表的分区有问题....


问过业务以后, 原来是这个功能还没做完, 所以表相关的操作并没有一直执行;
但是这个功能的页面没有屏蔽, 所以对应的那条语句是有可能被触发的;


考虑到用那条语句可以必现这个crash, 且输出的堆栈信息和之前完全一致,
所以确定是这个分区表的分区缺失的前提下, 触发那个查询语句的时导致了MySQL的Crash;


处理方式:
虽然最后还是找到了问题所在, 但是最开始的时候还是被buffer和内存使用率的现象误导了, too young......
PS:本来还是觉得分区表在5.7改进了一点以后, 应该还挺好用的.....恩, 现在持保留意见....._(:з

首页 上一页 1 2 3 下一页 尾页 2/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇MySQL内存使用率无限增长 下一篇MySQL的逻辑备份(mydumper+mysqld..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目