java jdbc mysql连接器:长时间空闲后如何解决断开连接

Posted

技术标签:

【中文标题】java jdbc mysql连接器:长时间空闲后如何解决断开连接【英文标题】:java jdbc mysql connector: how to resolve disconnection after a long idle time 【发布时间】:2011-03-10 01:14:37 【问题描述】:

我正在使用red5 1.0.0rc1 创建一个在线游戏。 我正在使用 jdbc mysql 连接器 v5.1.12 连接到 MySQL 数据库

似乎在空闲几个小时后,我的应用程序可以继续运行查询,因为与数据库的连接已关闭,我必须重新启动应用程序。

我该如何解决这个问题?

冷杉

【问题讨论】:

【参考方案1】:

MySQL JDBC 驱动程序具有自动重新连接功能,有时会很有帮助;请参阅“Driver/Datasource Class Names, URL Syntax and Configuration Properties for Connector/J”1,并阅读注意事项。

第二种选择是使用 JDBC 连接池。

第三种选择是执行查询以测试您的连接在每个事务开始时是否仍然有效。如果连接不存在,请将其关闭并打开一个新连接。一个常见的查询是SELECT 1。另见:

Cheapest way to to determine if a MySQL connection is still alive

一个简单的解决方案是更改 MySQL 配置属性以将会话空闲超时设置为一个非常大的数字。然而:

如果您的应用程序可能很长时间处于空闲状态,这将无济于事。 如果您的应用程序(或其他一些应用程序)正在泄漏连接,增加空闲超时可能意味着丢失的连接会无限期地保持打开状态......这对数据库内存利用率不利。

1 - 如果链接中断(再次),请谷歌搜索引用的页面标题,然后编辑答案以使用新 URL 更新它。

【讨论】:

【参考方案2】:

好吧,你重新打开连接。

连接池(强烈推荐,顺便说一句,如果您运行 Java EE,您的容器 - Tomcat、JBoss 等 - 可以通过 JNDI 提供javax.sql.DataSource,它可以为您处理池等)在处理连接之前验证连接通过运行一个非常简单的验证查询(如SELECT 1 或其他东西)。如果验证查询不起作用,它会丢弃连接并打开一个新连接。

增加连接或服务器超时往往只是推迟不可避免的事情。

【讨论】:

【参考方案3】:

我的应用程序遇到了同样的问题,我删除了空闲超时标签 就是这样

真的很好用 试试这个,我使用的是 Jboss 服务器,因为我在 mysql-ds.xml 文件中进行了以下更改。

如果您还有任何疑问,请告诉我

【讨论】:

【参考方案4】:

正常的 JDBC 习惯用法是在最短的可能范围内获取关闭Connection(以及StatementResultSet),即在与您执行查询时方法的 try-finally 块完全相同。您不应该一直保持连接打开。数据库迟早会超时并回收它。在 MySQL 中,默认为 8 小时后。

要提高连接性能,您应该考虑使用连接池,例如c3p0 (here's a developer guide)。请注意,即使使用连接池,您仍然必须编写正确的 JDBC 代码:在尽可能短的范围内获取和关闭所有资源。连接池将反过来担心实际关闭连接或只是将其释放回池以供进一步重用。

这是一个启动示例,您的方法从数据库中检索实体列表应如下所示:

public List<Entity> list() throws SQLException 
    // Declare resources.
    Connection connection = null;
    Statement statement = null;
    ResultSet resultSet = null;
    List<Entity> entities = new ArrayList<Entity>();

    try 
        // Acquire resources.
        connection = database.getConnection();
        statement = connection.createStatement("SELECT id, name, value FROM entity");
        resultSet = statement.executeQuery();

        // Gather data.
        while (resultSet.next()) 
            Entity entity = new Entity(); 
            entity.setId(resultSet.getLong("id"));
            entity.setName(resultSet.getString("name"));
            entity.setValue(resultSet.getInteger("value"));
            entities.add(entity);
        
     finally 
        // Close resources in reversed order.
        if (resultSet != null) try  resultSet.close();  catch (SQLException logOrIgnore) 
        if (statement != null) try  statement.close();  catch (SQLException logOrIgnore) 
        if (connection != null) try  connection.close();  catch (SQLException logOrIgnore) 
    

    // Return data.
    return entities;

另见:

DAO tutorial - How to write proper JDBC code

【讨论】:

【参考方案5】:

您是否定义了验证查询(如选择 1)?如果没有,使用验证查询会有所帮助。

【讨论】:

【参考方案6】:

您可以查看here 以了解类似问题。

将 '?autoReconnect=true' 附加到数据库的 JDBC URL(不带引号)的末尾对我有用。

【讨论】:

【参考方案7】:

我发现 ?autoReconnect=true 对我不起作用。

我所做的只是创建一个名为:executeQuery 的函数:

private ResultSet executeQuery(String sql, boolean retry) 
    ResultSet resultSet = null;
    try 
        resultSet = getConnection().createStatement().executeQuery(sql);
     catch (Exception e) 
            // disconnection or timeout error
        if (retry && e instanceof CommunicationsException || e instanceof MySQLNonTransientConnectionException
                        || (e instanceof SQLException && e.toString().contains("Could not retrieve transation read-only status server"))) 
            // connect again        
            connect();
            // recursive, retry=false to avoid infinite loop
            return executeQuery(sql,false);
        else
            throw e;
        
    
    return resultSet;

我知道,我正在使用字符串来获取错误.. 需要做得更好.. 但这是一个好的开始,并且可以工作:-)

这几乎都是断开连接的原因。

【讨论】:

以上是关于java jdbc mysql连接器:长时间空闲后如何解决断开连接的主要内容,如果未能解决你的问题,请参考以下文章

终止空闲的mysql连接

关于MySql8小时空闲后连接超时问题(testOnBorrow,logAbandoned等)

在 JDBC 中停止或终止长时间运行的查询

MySQL数据库的基础架构

Spring REST - 经过较长的空闲时间后,第一次调用需要很长时间(5-10 秒)

如何正确处理连接空闲超时错误