Java MySQL/Hibernate-如何调试不断下降的MySQL池连接?

Java MySQL/Hibernate-如何调试不断下降的MySQL池连接?,java,mysql,database,hibernate,orm,Java,Mysql,Database,Hibernate,Orm,几个月来,我的web应用程序运行平稳,但在过去一两周里,它不断断开与MySQL服务器的连接。我不是DBA,也不知道如何调试它 以下是我所知道的: 连接似乎每隔几个小时就会中断一次。有时在白天,但总是在晚上 我的实验室有一个MySQL服务器,为多个应用程序托管数据库 目前,我们有46个到MySQL服务器的连接 据我所知,没有其他应用程序遇到此问题 我的应用程序与另一个应用程序使用相同的堆栈、配置甚至代码连接到DB。另一个应用程序每天支持大约200个用户,自2013年以来一直运行平稳 两个应用程序都

几个月来,我的web应用程序运行平稳,但在过去一两周里,它不断断开与MySQL服务器的连接。我不是DBA,也不知道如何调试它

以下是我所知道的:

  • 连接似乎每隔几个小时就会中断一次。有时在白天,但总是在晚上
  • 我的实验室有一个MySQL服务器,为多个应用程序托管数据库
  • 目前,我们有46个到MySQL服务器的连接
  • 据我所知,没有其他应用程序遇到此问题
  • 我的应用程序与另一个应用程序使用相同的堆栈、配置甚至代码连接到DB。另一个应用程序每天支持大约200个用户,自2013年以来一直运行平稳
  • 两个应用程序都使用Hibernate ORM;这是我所知的唯一配置:

    <!-- TomcatJDBCConnectionProvider class is common to both applications -->
    <property name="hibernate.connection.provider_class">org.hibernate.connection.TomcatJDBCConnectionProvider</property>
    <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
    <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
    <property name="hibernate.connection.pool_size">5</property>
    <property name="hibernate.current_session_context_class">thread</property>
    <property name="hibernate.tomcatJdbcPool.validationQuery">SELECT 1</property>
    <property name="hibernate.tomcatJdbcPool.testOnBorrow">true</property>
    <property name="hibernate.enable_lazy_load_no_trans">true</property>
    
    它似乎在堆栈跟踪上迭代,找到带有文本
    “放弃的连接清理线程”
    的跟踪,然后手动停止它。似乎这可能与我的问题有关

    编辑2015年9月21日:

    这个周末我的申请被驳回了。这是昨天的错误日志中的堆栈跟踪(我相信它已经停止了):

    以下是我的MySQL连接变量:

    mysql>  SHOW VARIABLES LIKE '%connect%';
    +-----------------------------------------------+-----------------+
    | Variable_name                                 | Value           |
    +-----------------------------------------------+-----------------+
    | character_set_connection                      | utf8            |
    | collation_connection                          | utf8_general_ci |
    | connect_timeout                               | 5               |
    | default_master_connection                     |                 |
    | extra_max_connections                         | 1               |
    | init_connect                                  |                 |
    | max_connect_errors                            | 100             |
    | max_connections                               | 100             |
    | max_user_connections                          | 0               |
    | performance_schema_session_connect_attrs_size | 512             |
    +-----------------------------------------------+-----------------+
    
    mysql>  SHOW VARIABLES LIKE '%timeout%';
    +-----------------------------+----------+
    | Variable_name               | Value    |
    +-----------------------------+----------+
    | connect_timeout             | 5        |
    | deadlock_timeout_long       | 50000000 |
    | deadlock_timeout_short      | 10000    |
    | delayed_insert_timeout      | 300      |
    | innodb_flush_log_at_timeout | 1        |
    | innodb_lock_wait_timeout    | 50       |
    | innodb_rollback_on_timeout  | OFF      |
    | interactive_timeout         | 28800    |
    | lock_wait_timeout           | 31536000 |
    | net_read_timeout            | 30       |
    | net_write_timeout           | 60       |
    | slave_net_timeout           | 3600     |
    | thread_pool_idle_timeout    | 60       |
    | wait_timeout                | 28800    |
    +-----------------------------+----------+
    
    编辑2015年9月22日:

    严重的Tomcat错误会导致问题吗?我看到一个与数据库无关的错误,关于解析日期:

    22-Sep-2015 10:09:53.481 SEVERE [http-apr-8080-exec-26] org.apache.catalina.core.StandardWrapperValve.invoke Servlet.service() for servlet [edu.mssm.pharm.maayanlab.Harmonizome.page.DatasetPage] in context with path [/Harmonizome] threw exception [javax.servlet.ServletException: javax.servlet.jsp.JspException: In &lt;parseDate&gt;, a parse locale can not be established] with root cause
     javax.servlet.jsp.JspException: In &lt;parseDate&gt;, a parse locale can not be established
        at org.apache.taglibs.standard.tag.common.fmt.ParseDateSupport.doEndTag(ParseDateSupport.java:147)
    
    正在附加堆内存使用率的JConsole输出:

    用于线程使用的JConsole输出;它大约从24-25岁开始,当我开始使用这个网站时,它跳到了34岁。即使在关闭浏览器窗口后,它仍然存在:

    编辑2015年9月23日:

    在问题开始之前,我改变了一件事,那就是如何处理Hibernate事务。以前,我禁用了
    enable\u lazy\u load\u no\u trans
    (这是默认设置)。以前,我使用的是“”模式。人们似乎不喜欢视图中的开放会话模式,所以我启用了
    启用\u lazy\u load\u no\u trans
    。因此,我有如下代码:

    List<MyObjects> myObjects = null;
    try {
        HibernateUtil.beginTransaction();
        myObjects = // fetch my objects from the DB
        HibernateUtil.commitTransaction();
    } catch (HibernateException he) {
        HibernateUtil.rollbackTransaction();
    } finally {
        HibernateUtil.close();
    }
    
    // render myObjects in JSP/JSTL
    // this JSP may lazily load related objects
    
    List myObjects=null;
    试一试{
    HibernateUtil.beginTransaction();
    myObjects=//从数据库获取我的对象
    HibernateUtil.commitTransaction();
    }捕获(冬眠异常he){
    HibernateUtil.rollbackTransaction();
    }最后{
    HibernateUtil.close();
    }
    //在JSP/JSTL中呈现MyObject
    //此JSP可能会延迟加载相关对象
    

    回想起来,这似乎。。。有问题的我不知道Hibernate什么时候“放开”对象。

    Hibernate错误有点抽象,有时通过堆栈跟踪发现错误可能很棘手。我认为这可能是您的应用程序的问题,可能在某些情况下您没有正确关闭Hibernate连接,或者您的应用程序可能存在内存泄漏

    您是否尝试过使用JDK中的
    jconsole
    监视应用程序

    您可以在Java参数中的Tomcat配置控制台上设置它(我假设您使用的是Tomcat),以启用
    jconsole

    -Dcom.sun.management.jmxremote
    -Dcom.sun.management.jmxremote.port=8086
    -Dcom.sun.management.jmxremote.ssl=false
    -Dcom.sun.management.jmxremote.authenticate=false
    
    然后连接到远程进程,例如

    localhost:8086 
    
    并在执行使应用程序停止的操作时观察线程

    编辑


    如果您没有使用Tomcat,并且您正在Windows环境中运行应用程序,您可以使用例如监视线程并监视应用程序。

    从您提供的堆栈跟踪中,我可以得出一个结论:您只是在运行连接

    这可能是由于长时间运行的事务造成的,可能是由于查询速度慢或应用程序事务边界不正确

    我建议您开始使用,它支持Tomcat DBCP,并更好地了解连接和事务使用。 FlexyPool提供了许多您可能感兴趣的功能,如连接获取时间和租赁时间


    为了安全起见,还需要检查MySQL驱动程序的版本,看看您是否在一个过时的库上运行。

    您的连接池似乎无法在超时时间内返回到Hibernate的免费连接。这是因为应用程序具有很长的事务或事务死锁。您可以尝试以下选项来修复该错误

  • 在下面的行中更改您的连接池大小

    5

  • 将池大小设置为10左右,然后进行测试。您应该密切关注到数据库的连接数。如果超过mysql数据库连接限制,请更改mysql服务器的
    max_connections
    ,并继续测试

  • 使用另一个连接池。我建议使用ApacheCommonsDBCP2。dbcp2的Maven依赖项如下所示

    
    org.apache.commons
    commons-dbcp2
    2.1
    

  • 将dbcp2添加到POM中,然后使用应用程序配置dbcp2

    如果是解决方案,则应用程序只有长事务。有时,它可能会将发生的情况降到最低,如果仍然发生,那么您的应用程序肯定会有事务死锁。因此,您必须确定代码中可能存在的问题


    还有其他替代解决方案,例如将等待超时更改为更高的值。但这对应用程序性能没有好处,对于事务死锁也没有任何意义。最后,为了提高数据库的性能,您应该记住在进一步的开发中关注事务管理和数据库结构。

    内存问题?在部署Mysql和应用程序的机器上部署了其他应用程序吗?我对这个连接池实现没有经验,但我会开始调试QueryTimeoutInterceptor:@Gaurav,其他几个小应用程序正在同一台机器上运行。我们有一个集群
    -Dcom.sun.management.jmxremote
    -Dcom.sun.management.jmxremote.port=8086
    -Dcom.sun.management.jmxremote.ssl=false
    -Dcom.sun.management.jmxremote.authenticate=false
    
    localhost:8086