现象: 
        旗舰店运价库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)

转载于:https://www.cnblogs.com/DengGao/p/linx_cernel_bug.html

linux内核3.6版本及以下的bug引发的故障--cpu使用率100%相关推荐

  1. linux的内核和发行版本号,【编测编学】linux内核及发行版本相关知识

    之前很多孩子就和我说老师我会linux,我就会反问,你学软件测试,你会linux你知道linux的东西如何和企业结合吗? 不是你只会一些cd.chmod.chown.ps.find.tar.vim.v ...

  2. Linux内核4.14版本:ARM64的内核启动过程(二)——start_kernel

    目录 1. rest_init 2. init 进程(kernel_init) 2.1 kernel_init_freeable 2.1.1 do_basic_setup 2.1.2 prepare_ ...

  3. 查看linux内核信息及版本信息

    linux内核信息及版本信息 1.查看linux内核信息的命令:  uname 命令比较常用的参数:  uname    -r    内核版本信息,也就是说可以查看内核的当前版本.           ...

  4. linux cpu占用100原因查询,如何根据查询异常时间节点和连接进而确定CPU使用率100%的原因...

    本文在介绍如何根据查询异常时间节点和连接进而确定CPU使用率100%的原因的基础上,重点探讨了其具体步骤,本文内容紧凑,希望大家可以有所收获. 排查 Linux 实例异常 CPU 使用率 100% 使 ...

  5. Linux生产环境CPU使用率100%,教你定位到具体函数

    在我们项目部署上线的时候,我们是不是会经常去Linux服务器上查查服务器的CPU使用率,或者是运维经常会盯Linux的CPU使用率,发现监控报了60%的一般就会报警了,到了100%那就惨啦,做我开发的 ...

  6. 【Linux 内核】编译 Linux 内核 ① ( 下载指定版本的 Linux 内核源码 | Linux 内核版本号含义 | 主版本号 | 次版本号 | 小版本号 | 稳定版本 )

    文章目录 一.下载 Linux 内核 1.下载最新版本 Linux 内核 2.下载指定版本 Linux 内核 二.Linux 内核版本号含义 一.下载 Linux 内核 1.下载最新版本 Linux ...

  7. linux内核长期支持版本,Linux Kernel 3.12长期支持分支迎来第63个维护版本

    今天,Linux内核开发者Jiri Slaby宣布长期支持分支Linux Kernel 3.12迎来第63个维护更新版本.在Linux Kernel 3.12.63版本中共计对104份文件进行了调整, ...

  8. linux内核和发行版本的关系,简述Linux内核和Linux发行版的区别

    做服务器运维工作,要经常和Linux的版本号打交道,但一直搞不明白Linux内核和Linux发行版到底是个啥东西.其实要理解Linux内核和Linux发行版之间的关系,只要能理解下面的关系就可以了: ...

  9. Linux内核及其发行版本

    文章目录 Linux内核 Linux发行版 Linux发行版本发展图: Linux内核 Linux内核是操作系统内部操作和控制硬件设备的核心程序,它是由芬兰人林纳斯开发的. 内核效果图: 说明: 真正 ...

最新文章

  1. 虚拟机下运行linux通过nat模式与主机通信、与外网连接
  2. APACHE-TOMCAT集群环境部署
  3. 常见排序算法之冒泡排序
  4. JavaScript二进制、八进制和十六进制数值
  5. python生成时间戳_Python 获取时间戳
  6. retext代码高亮_实例简介Markdown格式
  7. 长连接与心跳包 Persistent connection and HearBeats
  8. 2008秋季-计算机软件基础-0922课堂用例(2)
  9. 工作 3 年和读研 3 年哪个更值?
  10. 如何做网站推广?如何提高网站浏览量?
  11. ESP32 学习笔记(二十一)电源管理
  12. 使用PIL改变图像分辨率
  13. SDKD 2021 C3 7th Round
  14. 微信缓存dat怎么转图片_PC微信dat文件如何转换为图片?
  15. Imu_heading使用
  16. Android判断当前使用数据流量的是哪张卡
  17. 聚焦:ZK-SNARK 技术
  18. 用FPGA实现半加器
  19. 学python历程中
  20. 抖音直播间千川投放有用吗?直播间投放分析有什么技巧

热门文章

  1. (八) shiro + spring + mybatis整合开发
  2. 女生做大数据有发展前景吗?能学会吗?
  3. 怎么才能学好Java?月薪35K阿里P9程序员给出了这样的建议!
  4. 女主播还是女主播???
  5. 实现JavaScript继承
  6. 监听localStorage变化(同页面监听)
  7. [编程题]表达式合法判断
  8. 安装虚拟机VMware12步骤
  9. linux中的du 命令详解
  10. @RequiredArgsConstructor用法