mysql连接超时后无法从apache DBCP连接池获取连接

Posted

技术标签:

【中文标题】mysql连接超时后无法从apache DBCP连接池获取连接【英文标题】:Unable to get connection from apache DBCP connection pooling after mysql connection timeout 【发布时间】:2014-01-09 00:34:21 【问题描述】:

这是一种很奇怪的情况,我认为它在处理 mysql 连接对象时最常见。下面是场景

在执行 sql 语句之前,我使用 apache DBCP 连接池获得了一个连接对象。一切正常,直到发生 mysql 连接超时(8 小时)。所以在这个连接池之后没有返回任何连接对象,这使得任何sql操作都等到下次重启tomcat服务器。如果没有 DBCP,我们可能会得到通信异常,表示没有发送或接收数据包。这就是我选择 apache DBCP 的原因,认为它将管理连接池。下面是我的代码

import javax.sql.DataSource;
import org.apache.log4j.Logger;
import org.apache.commons.dbcp.BasicDataSource;

DataSource dataSource
BasicDataSource ds = new BasicDataSource();
ds.setDriverClassName(driver);
ds.setUsername(username);
ds.setPassword(password);
ds.setUrl(url + "/" + dbname);
dataSource = ds;
logger.info("Getting connection from DBCP connection pool...");
con = dataSource.getConnection();
logger.info("MYSQL DB Connection Creation Successful...");

我注意到 apache DBCP 使用单例模式来创建连接,因此每次我请求时都不会创建新的连接对象。如果我做错了什么,请给我一个出路并澄清我。我不适合以下解决方案

增加 mysql 超时时间(bcoz mysql 很常见,我认为增加不是一个好的解决方案) 出现问题时重新启动 tomcat 服务器(这不是一个很好的解决方案,因为我们不能一直在那里,也没有脚本...... :)

请给我一个出路。谢谢

【问题讨论】:

您可以分享日志中的任何异常情况? 我打印了这一行“从 DBCP 连接池获取连接..”,但没有打印这一行“MYSQL DB 连接创建成功...”。没有错误信息被打印出来..!! 【参考方案1】:

我没有在您的代码中获得 DBCP 连接池的设置。只需按照文档中的说明尝试下面的连接池代码即可。

PoolProperties p = new PoolProperties();
          p.setUrl("jdbc:mysql://localhost:3306/mysql");
          p.setDriverClassName("com.mysql.jdbc.Driver");
          p.setUsername("root");
          p.setPassword("password");
          p.setJmxEnabled(true);
          p.setTestWhileIdle(false);
          p.setTestOnBorrow(true);
          p.setValidationQuery("SELECT 1");
          p.setTestOnReturn(false);
          p.setValidationInterval(30000);
          p.setTimeBetweenEvictionRunsMillis(30000);
          p.setMaxActive(100);
          p.setInitialSize(10);
          p.setMaxWait(10000);
          p.setRemoveAbandonedTimeout(60);
          p.setMinEvictableIdleTimeMillis(30000);
          p.setMinIdle(10);
          p.setLogAbandoned(true);
          p.setRemoveAbandoned(true);
          p.setJdbcInterceptors(
            "org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;"+
            "org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer");
          DataSource datasource = new DataSource();
          datasource.setPoolProperties(p);

          Connection con = null;
          try 
            con = datasource.getConnection();
            Statement st = con.createStatement();
            ResultSet rs = st.executeQuery("select * from user");
            int cnt = 1;
            while (rs.next()) 
                System.out.println((cnt++)+". Host:" +rs.getString("Host")+
                  " User:"+rs.getString("User")+" Password:"+rs.getString("Password"));
            
            rs.close();
            st.close();
           finally 
            if (con!=null) try con.close();catch (Exception ignore) 
          

还可以阅读此document 中有关每个属性的信息。 希望这能解决你的问题

【讨论】:

【参考方案2】:

需要查看异常。然而,只是在黑暗中拍摄: 如果你看到类似

com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException

您可能想用 try/catch 包装它,然后在 catch 块中重新连接并重新运行您的查询。 检查MySQL docs 处理停滞的连接。

顺便说一句:这对 Spring 来说真的很简单——你可以配置数据源来恢复停滞的连接。

【讨论】:

以上是关于mysql连接超时后无法从apache DBCP连接池获取连接的主要内容,如果未能解决你的问题,请参考以下文章

DBCP连接回收问题

连接到 Maven 存储库时连接超时

Mysql----JDBC 连接池 DBCP C3P0

使用 Spring 和 DBCP 和 MySQL 设置连接时区

Apache Tomcat: mod_jk 连接超时cping/cpong timeout

DBCP连接池使用问题