linux内核3.6版本及以下的bug引发的故障--cpu使用率100%
现象:
旗舰店运价库cpu使用率100%,load升高,导致后续的请求失败。
重启服务器,cpu、load恢复正常。
触发条件:
(1)linux内核3.6版本及以下。 (线上机器大部分是2.6.32)
(2)mysql-connector-java5.1.31版本及以下。(各业务线需要自己check)
(3)mysql-client没有设置socketTimeout。 (各业务线需要自己check)
(4)杀死mysql-server与mysql-client的连接处于mysql-server端的线程。 (dba经常会杀死慢查询)
当(1)(2)(3)同时具备,只要触发(4),客户端连接线程就会死循环。杀死一个mysql-server端线程,客户端就会死循环一个,占用一个cpu内核。
具体原因:
Linux kernels version 3.6 and earlier (including 2.6.32) have a bug [1] which makes requests for the amount of available bytes to read in a socket in CLOSE_WAIT state to return 1 even after the EOF has been read.
This bug makes SocketInputStream.available return 1 for sockets in CLOSE_WAIT state and causes a seemly infinite loop in MysqlIO.clearInputStream where it attempts to read from the socket until the number of available bytes reaches 0, but there is nothing to read.
出处: https://bugs.mysql.com/bug.php?id=73053
mysql官网5.1.32版本的变更记录,有提到这个bug:
A bug in the Linux kernel version 3.6 and earlier caused the MysqlIO.clearInputStream() method to enter an endless loop. This fix changes the way the looping condition is evaluated, in order to avoid the problem. (Bug #19022745, Bug #73053)
出处:https://dev.mysql.com/doc/relnotes/connector-j/5.1/en/news-5-1-32.html
mysql驱动高版本(已兼容linux低版本内核的bug),附截图:

解决方案:
(1)升级mysql-connector-java版本到5.1.32及以上。 或者
(2)升级linux内核版本到3.7及以上。 或者
(3)客户端设置socket读超时时间。(杀死server端线程,客户端线程立马释放,没有到达超时时间。为什么能生效,不是很清楚,有知道的可以回复邮件)
推荐使用(1)
查问题的过程:
1. 重启机器,cpu使用率恢复正常。 但是保留一台机器做现场。
2. 使用jstack命令与top命令分析现场机器,发现执行时间长和cpu使用率高的线程,死循环在MysqlIO.clearInputStream()。
3. 在网上查阅资料,发现是linux内核3.6版本及以下的bug导致。 但是不知道怎么触发。
4. 询问dba,当时dba在杀死mysql-server端的慢查询,时间是吻合的。 猜测触发条件之一是,杀死mysql-server与mysql-client的连接 处于mysql-server端的线程。
复现过程:
1. 使用内核版本2.6.32的linux部署应用服务,应用服务使用的mysql-connector-java版本为5.1.21, mysql-client没有设置socketTimeout。 (与线上环境一致)
2. 更改应用服务里的sql语句,其实是增加了休眠,方便能在mysql-server端查看此线程。 sql语句由select... 变为 select sleep(10) ...
3. 调用http接口,触发测试的查询语句。
4. 登录mysql-server,使用命令 show processlist; 查看测试的查询语句,得到线程id。 kill + 线程id, 杀死正在执行的线程。
5. 应用服务器,cpu其中1核使用率达到100%, 并且http接口,一直没有响应返回(应用服务器线程死循环了)。
6. 重复步骤(3)、(4),每杀死mysql-server端的一个线程,cpu的一个核使用率就会达到100%。
注意:如果应用服务器 打过补丁tcp: fix FIONREAD/SIOCINQ, 无法复现。
几个实验:
1. 升级mysql-connector-java版本到5.1.34,其他条件不变。 杀死mysql-server端的线程,应用服务器cpu没有变化,mysql-client端线程立马释放。
2. 升级linux内核版本到3.18.48,其他条件不变。 杀死mysql-server端的线程,应用服务器cpu没有变化,mysql-client端线程立马释放。
3. 设置mysql-client端超时时间2分钟,其他条件不变。 杀死mysql-server端的线程,应用服务器cpu没有变化,mysql-client端线程立马释放。没有等到2分钟超时,mysql-client端线程立马释放。
当时分析问题的线程栈信息如下:
java.lang.Thread.State: RUNNABLE
at java.net.PlainSocketImpl.socketAvailable(Native Method)
at java.net.AbstractPlainSocketImpl.available(
AbstractPlainSocketImpl.java:478)
- locked <0x000000070ed04a40> (a java.net.SocksSocketImpl)
at java.net.SocketInputStream.available(SocketInputStream.java:245)
at com.mysql.jdbc.util.ReadAheadInputStream.fill(ReadAheadInputStream.java:72)
at com.mysql.jdbc.util.ReadAheadInputStream.skip(ReadAheadInputStream.java:300)
at com.mysql.jdbc.MysqlIO.clearInputStream(MysqlIO.java:948)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2404)
at com.mysql.jdbc.ConnectionImpl.pingInternal(Unknown Source)
at com.mysql.jdbc.ConnectionImpl.execSQL(Unknown Source)
- locked <0x000000070ed04c10> (a com.mysql.jdbc.JDBC4Connection)
at com.mysql.jdbc.ConnectionImpl.execSQL(Unknown Source)
at com.mysql.jdbc.StatementImpl.execute(Unknown Source)
- locked <0x000000070ed04c10> (a com.mysql.jdbc.JDBC4Connection)
at com.mysql.jdbc.StatementImpl.execute(Unknown Source)
linux内核3.6版本及以下的bug引发的故障--cpu使用率100%的更多相关文章
- 在linux系统中实现各项监控的关键技术(1)--cpu使用率的计算
转载自 Linux中通过/proc/stat等文件计算Cpu使用率 http://www.blogjava.net/fjzag/articles/317773.html proc文件系统 /proc文 ...
- Linux:CPU使用率100%排查方法
Linux作为一个多任务操作系统,将每个CPU的时间划分为很短的时间片,再通过调度器轮流分配给各个任务使用,因此造成多任务同时运行的错觉. CPU使用率 Linux作为一个多任务操作系统,将每个CPU ...
- 记java应用linux服务单个CPU使用率100%分析
之前在做项目的过程中,项目完成后在linux服务器上做性能测试,当服务跑起来的时候发现cpu使用率很奇怪,java应用把单个cpu跑满了,其他cpu利用率0%. 刚开始遇到这问题的时候我第一时间反应使 ...
- Linux内核版本类型
对于Linux内核发布的版本类型有如下,也是自己的理解: [mainline]:主线版本,由Linux Torvalds维护和发布. [stable/EOL]:稳定版本,每个由主线发布的版本都叫做稳定 ...
- 嵌入式系统Linux内核开发工程师必须掌握的三十道题(转)
嵌入式系统Linux内核开发工程师必须掌握的三十道题 如果你能正确回答以下问题并理解相关知识点原理,那么你就可以算得上是基本合格的Linux内核开发工程师,试试看! 1) Linux中主要有哪几种内核 ...
- Linux内核的整体架构
Linux内核的整体架构 作者:蜗蜗 发布于:2014-2-21 13:23 分类:Linux内核分析 原文:http://www.wowotech.net/linux_kenrel/11.html ...
- Linux内核头文件与内核与库的关系
看上一篇文章中对buildroot的介绍,里面的文档第 3.1.1.1 Internal toolchain backend 节内容 C库会去访问Linux kernel headers(*.h)文件 ...
- Gdb远程调试Linux内核遇到的Bug
知识共享许可协议本作品采用知识共享署名 4.0 国际许可协议进行许可.转载保留声明头部与原文链接https://luzeshu.com/blog/gdb-bug 本博客同步在http://www.cn ...
- 【转帖】Linux的历史----Linux内核剖析(一)
Linux的历史----Linux内核剖析(一) 2015年04月09日 10:51:09 JeanCheng 阅读数:11351更多 所属专栏: Linux内核剖析 版权声明:本文为博主原创文 ...
随机推荐
- sublime2创建一个html5的snippets文件
背景:跟了一个网上课程,老师哗啦啦敲代码,屏幕上只敲了几个字,键盘一操作,瞬间一大溜代码,看得我心惊肉跳连忙暂停抄抄抄. 举个简单的例子,我需要创建一个html文件.但是我不想每次都敲固定的格式.那么 ...
- Spring学习-- AOP入门动态代理
AOP 的拦截功能是由 java 中的动态代理来实现的.说白了,就是在目标类的基础上增加切面逻辑,生成增强的目标类(该切面逻辑或者在目标类函数执行之前,或者目标类函数执行之后,或者在目标类函数抛出异常 ...
- 转:A Painless Q-learning Tutorial (一个 Q-learning 算法的简明教程)
demo 参见 MDP DEMO 本文是对 http://mnemstudio.org/path-finding-q-learning-tutorial.htm 的翻译,共分两部分,第一部分为中文 ...
- 关于CRC循环冗余校验的总结(C#)
1. 实验要求 (1)通过CRC(循环冗余校对)序列的计算,掌握C#语言中类的静态方法与动态方法的区别. (2)Shell与Windows Form 的通信作为扩展提高内容. 2. 实验内容 主要工 ...
- c语言指针学习【转】
前言 近期俄罗斯的陨石.四月的血月.五月北京的飞雪以及天朝各种血腥和混乱,给人一种不详的预感.佛祖说的末法时期,五浊恶世 ,十恶之世,人再无心法约束,道德沦丧,和现在正好吻合.尤其是在天朝,空气,水, ...
- 【BZOJ2738】矩阵乘法 [整体二分][树状数组]
矩阵乘法 Time Limit: 20 Sec Memory Limit: 256 MB[Submit][Status][Discuss] Description 给你一个N*N的矩阵,不用算矩阵乘 ...
- 【Foreign】无聊的计算姬 [Lucas][BSGS]
无聊的计算姬 Time Limit: 10 Sec Memory Limit: 256 MB Description Input Output Sample Input 6 2 2 3 4 3 2 ...
- Django-models class Meta:元类
Django模型之Meta选项详解 Model 元数据就是 "不是一个字段的任何数据" -- 比如排序选项, admin 选项等等. Django模型类的Meta是一个内部类, ...
- 【反演复习计划】【bzoj3529】数表
Orz PoPoQQQ大爷 按照他ppt的解法,这题可以划归到之前的题了OrzOrz 跪wy写的题解(Stealth Assassin)https://www.luogu.org/wiki/show? ...
- OC学习篇之---代理模式
何实现代理模式的. 这里举一个简单的例子: 小孩类,护士类,保姆类,其中小孩类有两个方法:wash和play 这里代理对象就是:护士类.保姆类,小孩类是被代理对象. 看一下代码: 首先看一下小孩类: ...