开发者

java jdbc mysql connector: how to resolve disconnection after a long idle time

I'm using red5 1.0.0rc1 to create an online game. I'm connecting to a MySQL database using a jdbc mysql connector v5.1.12

it seems that after several hours of idle my application can continue running queries开发者_如何学Python because the connection to the db got closed and i have to restart the application.

how can I resolve the issue ?

Kfir


The MySQL JDBC driver has an autoreconnect feature that can be helpful on occasion; see "Driver/Datasource Class Names, URL Syntax and Configuration Properties for Connector/J"1, and read the caveats.

A second option is to use a JDBC connection pool.

A third option is to perform a query to test that your connection is still alive at the start of each transaction. If the connection is not alive, close it and open a new connection. A common query is SELECT 1. See also:

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

A simple solution is to change the MySQL configuration properties to set the session idle timeout to a really large number. However:

  • This doesn't help if your application is liable to be idle for a really long time.
  • If your application (or some other application) is leaking connections, increasing the idle timeout could mean that lost connections stay open indefinitely ... which is not good for database memory utilization.

1 - If the link breaks (again), please Google for the quoted page title then edit the answer to update it with the new URL.


Well, you reopen the connection.

Connection pools (which are highly recommended, BTW, and if you run Java EE your container - Tomcat, JBoss, etc - can provide a javax.sql.DataSource through JNDI which can handle pooling and more for you) validate connections before handing them out by running a very simple validation query (like SELECT 1 or something). If the validation query doesn't work, it throws away the connection and opens a new one.

Increasing the connection or server timeout tends to just postpone the inevitable.


I had the Same issue for my application and I have removed the idle time out tag Thats it

It really worked fine try this, I was using the Jboss server, in that i have made the following change in mysql-ds.xml file.

Let me know if you have any more doubts


The normal JDBC idiom is to acquire and close the Connection (and also Statement and ResultSet) in the shortest possible scope, i.e. in the very same try-finally block of the method as you're executing the query. You should not hold the connection open all the time. The DB will timeout and reclaim it sooner or later. In MySQL it's by default after 8 hours.

To improve connecting performance you should really consider using a connection pool, like c3p0 (here's a developer guide). Note that even when using a connection pool, you still have to write proper JDBC code: acquire and close all the resources in the shortest possible scope. The connection pool will in turn worry about actually closing the connection or just releasing it back to pool for further reuse.

Here's a kickoff example how your method retrieving a list of entities from the DB should look like:

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;
}

See also:

  • DAO tutorial - How to write proper JDBC code


Do you have a validationQuery defined (like select 1)? If not, using a validation query would help.


You can check here for a similar issue.

Append '?autoReconnect=true' to the end of your database's JDBC URL (without the quotes) worked for me.


I saw that ?autoReconnect=true wasn't working for me.

What I did, is simply creating a function called: executeQuery with:

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;
}

I know, I'm using string to get the error.. need to do it better.. but it's a good start, and WORKS :-)

This will almost all reasons from a disconnect.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜