5

Hello all I have a basic Storm application set up where it receives a stream of tweets and stores them in a MySQL database. The application works great for the first ~23 hours or so then it starts giving the following error:

SQL Exception
SQL State: 08003

After it does this a few times it dies. I'm using the standard JBDC connector to connect to the database from Java. The code for the functions for storing and setting up the DB connection are as follows:

private String _db="";
private Connection conn = null;
private PreparedStatement pst = null;

public ArchiveBolt(String db){
    _db = db;
}

private void setupConnection() {
    //Connect to the database
    try {
        Class.forName("com.mysql.jdbc.Driver");
        conn = DriverManager.getConnection("jdbc:mysql://localhost:8889/twitter_recording", "root", "root");
    } catch (Exception e){
        e.printStackTrace();
    }
}

public void execute(Tuple tuple, BasicOutputCollector collector) {

    Status s = (Status) tuple.getValue(0);

    //setup the connection on the first run through or if the connection got closed down
    try {
        setupConnection();
    } catch (Exception e) {
        // TODO: handle exception
        System.out.println(e.toString());
    }


    try {

        pst = conn.prepareStatement("INSERT INTO " + _db + " (tweet)" +
                                    "VALUES (?);");

        pst.setString(1, s.toString());

        //execute the SQL
        pst.executeUpdate();

    } catch (SQLException ex) {
        // handle any errors
        System.out.println("SQLException: " + ex.getMessage());
        System.out.println("SQLState: " + ex.getSQLState());
        System.out.println("VendorError: " + ex.getErrorCode());

        if(ex.getSQLState().equals("08003")){
            setupConnection();
        }

    } finally {
        try {
            conn.close();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

After it became apparent that it was crashing because of a 08003 error I decided that if it threw that error it should retry the set up of the connection, however that didn't help either. Could anyone point me in the right direction for solving this issue?

Matthias J. Sax
  • 59,682
  • 7
  • 117
  • 137
Chris Maness
  • 1,682
  • 3
  • 22
  • 40
  • [08003 Connection does not exist](http://dev.mysql.com/doc/refman/5.0/en/connector-odbc-reference-errorcodes.html) – John Dvorak Nov 14 '12 at 22:22
  • Does the connection always break at the same time of the day? If so, perhaps the connection is broken by some scheduled event (e.g. the DB gets rebooted daily). – John Dvorak Nov 14 '12 at 22:28
  • Yes I know this. That's why I had the connection setup again in the case that it run in to this error. As shown above `catch (SQLException ex) { // handle any errors System.out.println("SQLException: " + ex.getMessage()); System.out.println("SQLState: " + ex.getSQLState()); System.out.println("VendorError: " + ex.getErrorCode()); if(ex.getSQLState().equals("08003")){ setupConnection(); } }` – Chris Maness Nov 14 '12 at 22:28
  • If that's the daily reboot, it's likely the DB will be down for several minutes and trying to reconnect immediately will fail. – John Dvorak Nov 14 '12 at 22:29
  • The connection doesn't break the same time each day. It's just always around 23 hours from when I started it. I control the DB and for this phase of the project it's up 24/7 continually. – Chris Maness Nov 14 '12 at 22:31
  • I admit, pinging `localhost` should always succeed. Sot so much for remote DBs, though. – John Dvorak Nov 14 '12 at 22:32
  • Yeah, I've tried all of the obvious solutions to the problem. – Chris Maness Nov 14 '12 at 22:36
  • Older versions of Windows (can't tell if W98 or W3.1) always crashed after ~3.5 days when they overflowed some counter. One counter that comes to my mind is 2^32 bytes. Even then, I don't get why the connection doesn't get reset. – John Dvorak Nov 14 '12 at 22:38
  • Perhaps you need to tell the `DriverManager` to drop the current (non-working) connection before you establish a new one. – John Dvorak Nov 14 '12 at 22:40

1 Answers1

3

After it became apparent that it was crashing because of a 08003 error I decided that if it threw that error it should retry the set up of the connection, however that didn't help either. Could anyone point me in the right direction for solving this issue?

There are basically two problems here that need to be solved:

  • Why are the connections getting lost in the first place?
  • Why isn't your attempt to reconnect succeeding?

For the first problem, you should take a look at the MySQL logs to see if there are any indications there. And also, check for SQL exceptions immediately prior to the (repeated) "state 080003" exceptions. The latter are simply telling you that the connection has died previously.

My guess is that the problem is one of the following:

  • The MySQL server has timed out the connection due to inactivity. You can change the connection timeout in the MySQL configs if this is the problem.

  • Your application may be slowly leaking JDBC connections.

For the second problem, the general approach is correct, but your code doesn't match the description. In fact, it looks like it is always trying to establish a new database connection each time your execute method is called. This renders the reconnection call in your exception handler pointless. (OTOH, the code show signs that someone has been "beating on it" to try to get it to work ... and that could well be part of the problem.)

I would check that setupConnection is being called when it needs to be, and look for any exception that might be thrown. In addition, you should make sure that you explicitly close() the dead connection object ... and rethink / recode your connection management so that it doesn't leak.


For the record, there is a connection URL parameter called "autoReconnect" that in the distant past used to "deal" with lost connections. Unfortunately, the original implementation was unsafe, so they effectively disabled it; see this Question for details: Why does autoReconnect=true not seem to work?

Community
  • 1
  • 1
Stephen C
  • 698,415
  • 94
  • 811
  • 1,216