zoukankan      html  css  js  c++  java
  • 上Mysql com.mysql.jdbc.StatementImpl$CancelTask内存泄漏问题和解决方法

    近来在负责公司短信网关的维护及建设,随着公司业务发展对短信依赖越来越严重了,短信每天发送量也比曾经每天40多w发送量暴增到每天达到200w发送量。由于是採用Java做发送底层,压力递增情况下不可避免的面对内存问题。

    在发送量接近200w情况下,出现内存泄露问题了。

    经过对系统执行检查发现:

            1)每次重新启动系统3-4个小时后。均发现一点不稳定;

            2)在3-4个小时后。出现out of memory的错误:java.lang.OutOfMemoryError: GC overhead limit exceeded

    发现这个问题后,直接通过JMS获取监控日志,发现系统的内存回收存在异常,gc压力很大并且存在明显内存积压。




    然后直接把系统的内存down下来分析,发现的确存在内存积压情况:


    这个是mysql的一个定时任务的,这个定时任务主要作用是在用于做查询超时的。

    简单举个样例,系统在运行一个sql查询情况下。jdbc会给你一个超时时间。为了保证超时时间后,能够关闭statement,会打开一个保护关闭的定时任务。假设超时情况下,sql还没响应运行,cancel task就会运行关闭任务。由于c3p0的默认设置的超时时间为25s(<setting name="defaultStatementTimeout" value="25000" />),意味这个25s内,在运行大量sql情况下。cancel task积压到了一定程度,就会造成系统不稳定。

    (最后发现这个并非根本原因,仅仅是表象)

    可是系统本身就有通过mysql做发送队列的,本身对mysql操作许多。假设仅仅是对代码层面下优化基本杯水车薪。

    在时间紧迫的情况下。短时间内稳定业务才是最重要的任务。

    被逼依据以上现状採用了暂时方案解决。


    暂时方案

            通过以上推断,基本能够判定cancel task在某组线程执行应该会形成一个峰值,撑爆了JVM的堆。可是如今无法在停止业务执行做过多调试,所以当机立断,对JVM的内存扩大一倍以上,希望系统能够跨过一波内存峰值。结果把JVM的内存调整为故障时候的2倍时候,系统的内存又恢复到正常运作。只是cancel task最高值会占用到内存2G以上。尽管也是会回收,可是一直扩内存不是非常好的办法。


    解决方式

    系统採用的mysql jdbc 5.1.6的版本号,立马反编译mysql代码,发现下面问题。

    由于cancel task的timer在connection中静态存放。意味statement假设正常查询出结构,业务无法把cancel task内存回收才是故障根本原因。


    明白问题在mysql jdbc上面后。根本解决的方法应该查询mysql jdbc是否攻克了这个bug。

    在5.1.11版本号中找到这个bug的修复。更新后。内存泄漏故障得到解决。http://dev.mysql.com/doc/relnotes/connector-j/en/news-5-1-11.html


    讨论并协助谢国波感和锐利康。使故障得以圆满解决!

  • 相关阅读:
    URL地址中中文乱码详解(javascript中encodeURI和decodeURI方法、java.net.URLDecoder.encode、java.net.URLDecoder.decode)
    Java transient关键字使用小记
    java 序列化Serializable 详解
    JRE和JDK的区别
    JavaEE汇总
    Oracle汇总
    java提高篇(四)-----理解java的三大特性之多态
    SQL根据出生日期精确计算年龄、获取日期中的年份、月份
    PL/SQL学习笔记(四)之——删除重复记录
    PL/SQL学习笔记(二)
  • 原文地址:https://www.cnblogs.com/bhlsheji/p/5038370.html
Copyright © 2011-2022 走看看