MySQL超时过期后c3p0的连接抛出异常

Posted

技术标签:

【中文标题】MySQL超时过期后c3p0的连接抛出异常【英文标题】:Connection of c3p0 throws exception after MySQL timeout expired 【发布时间】:2014-12-23 16:52:45 【问题描述】:

我使用版本 0.9.2.1 的 c3p0 库在 Web 应用程序中创建连接池。 mysql超时后我得到异常:

"HTTP 状态 500 - 成功接收到的最后一个数据包 服务器是 627 301 毫秒前。最后一个数据包发送成功 到服务器是 627 302 毫秒前。比服务器长 'wait_timeout' 的配置值。你应该考虑 在您使用之前过期和/或测试连接有效性 应用程序,增加客户端的服务器配置值 超时,或使用 Connector/J 连接属性 'autoReconnect=true' 来避免这个问题。”

我尝试将 autoReconnect 参数附加到 JDBC url,但也没有效果。所以,这样我在我的应用程序中使用连接池:

为了测试,我将 MySQL 的 wait_timeout 设置为 180 秒

set @@global.wait_timeout=180;

show global variables like "wait_timeout";

+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| wait_timeout  |  180  |
+---------------+-------+

还有下一段代码

c3p0.properties

# JDBC paramters are ommited
# Basic pool configuration
c3p0.initialPoolSize=5
c3p0.minPoolSize=5
c3p0.maxPoolSize=50
c3p0.acquireIncrement=5
# Managing connection age
c3p0.maxConnectionAge=100
c3p0.maxIdleTime=90
# Configuring connection testing
c3p0.idleConnectionTestPeriod=30
c3p0.testConnectionOnCheckin=true
c3p0.preferredTestQuery=SELECT 1

DBConnectionUtil.java

public class DBConnectionUtil 
    // initialized through c3p0.properties
    private static ComboPooledDataSource ds = new ComboPooledDataSource();

    public static ComboPooledDataSource getConnectionPool() 
        return ds;
    

    public static void destroyConnectionPool() 
        ds.close();
    

    public static Connection getConnection() throws SQLException 
        return ds.getConnection();
    

UserDAO.java

public class UserDAO 

    private Connection connection;

    public UserDAO() throws SQLException 
        connection = DBConnectionUtil.getConnection();
    

    public User find(Integer id) throws SQLException 
        User user = null;
        PreparedStatement ps = connection.prepareStatement("SELECT * FROM `USERS` WHERE ID = ?");
        ps.setInt(1, id);
        ResultSet rs = ps.executeQuery();
        if (rs.next()) 
            user = new User();
            user.setId(rs.getInt("ID"));
            user.setName(rs.getString("NAME"));
            user.setUsername(rs.getString("USERNAME"));
            user.setPassword(rs.getString("PASSWORD"));
            user.setParentId(rs.getInt("PARENT_ID"));
        
        rs.close();
        ps.close();
        return user;
    

DAOUtil.java

public class DAOUtil 
    private static UserDAO userDAO;

    public static UserDAO getUserDAO() 
        return userDAO;
    

    static 
        try 
            userDAO = new UserDAO();
         catch (SQLException e) 
            throw new RuntimeException(e);
        
    

例如,在 MySQL wait_timeout 过期后,当我调用 DAOUtil.userDAO.find(id) 时,它会抛出上述异常。

请你帮我看看我做错了什么? 注意:我无法更改 MySQL ini 文件。

【问题讨论】:

【参考方案1】:

尝试关闭 Dao 类中的连接,并为每个对数据库的请求从连接池中请求新的连接。

Connection con;
try 
  con=DBConnectionUtil.getConnection();
  //some code here
 finally 
  if(con!=null)
      con.close();
   

而且将 Connection 作为对象字段是不安全的,最好将其用作局部变量,因为 Connection 不是线程安全的。

【讨论】:

它有帮助,谢谢!还有一个问题:如果我总是在每次查询后关闭连接会影响性能吗? 这就是你使用连接池的原因。建立与数据库的连接非常昂贵,但连接池已经有连接,您只需获取其中一个即可。当您在 Connection 上调用 close() 时,此 Connection 返回到池中,您可以再次使用它。

以上是关于MySQL超时过期后c3p0的连接抛出异常的主要内容,如果未能解决你的问题,请参考以下文章

无限超时的 HttpClient 抛出超时异常

HttpClient的PostAsync方法在2-3次超时请求后抛出Aggregate异常

MySql.Data.MySqlClient.MySqlException:超时已过期

SQL连接池超时

一种设置python函数执行超时时间 | 函数超时后不抛出异常的方法

如何在mysql数据库连接中使用抛出异常[重复]