sql >> Base de Datos >  >> RDS >> Mysql

¿Cómo manejar adecuadamente los interbloqueos de InnoDB en Java/JDBC?

Su código es esencialmente correcto. La excepción que surge cuando se produce un punto muerto es una SQLException . getSQLState() de la excepción método proporciona devuelve un código de error que proporciona información adicional sobre el error real.

También debe esperar un breve período de tiempo entre intentos, para no cargar demasiado su servidor.

Como adivinaste inteligentemente, establece un número máximo de intentos, o podrías terminar en un bucle infinito.

El código final podría verse así:

boolean oops;
int retries = 5;
Connection c = null;
Statement s = null;
ResultSet rs = null;    

do
{
    oops = false;
    c = null;
    s = null;
    rs = null;
    try
    {
        c = openConnection();
        s = c.createStatement();
        rs = s.executeQuery("SELECT stuff FROM mytable");
        fiddleWith(rs);
    }
    catch (SQLException sqlex)
    {
        oops = true;
        switch(sqlex.getErrorCode()())
        {
            case MysqlErrorNumbers.ER_LOCK_DEADLOCK:
                // deadlock or lock-wait time-out occured
                break;
            ...
        }
        Thread.sleep(1000); // short delay before retry
    }
    finally
    {
        if (rs != null) try {
            rs.close();
        } catch (SQLException e) {
            // some error handler here
        }

        if (s != null) try {
            s.close();
        } catch (SQLException e) {
            // some error handler here
        }

        if (c != null) try {
            c.close();
        } catch (SQLException e) {
            // some error handler here
        }

    }
}
while (oops == true && retries-- > 0);

Obviamente, el código anterior es subóptimo. Es posible que desee diferenciar los errores que se producen en el momento de la conexión y los errores en el momento de la ejecución. También podría detectar que después de algunos errores, hay pocas esperanzas de que funcione otro intento (por ejemplo, credenciales incorrectas o error de sintaxis SQL).

Hiciste muchas preguntas, pero intentaré responderlas todas:

Sí, ver arriba:SQLException son los indicados, con más información proporcionada por getErrorCode() o getSQLState() .

Una SQLException podría ser lanzado por prácticamente todos los métodos de todas las clases desde java.sql paquete.

Sí, ver arriba.

Obviamente, no debe volver a crear un PreparedStatement entre dos consultas. Solo necesita establecer nuevos valores para sus parámetros antes de llamar a executeQuery() otra vez. Por supuesto, si necesita ejecutar otra consulta, entonces una nueva PreparedStatement es obligatorio.

Un (nuevo) ResultSet el objeto es devuelto por Statement.executeQuery() , que representa el resultado de la consulta. Nunca creas tal objeto por ti mismo. Idealmente, llamará a ResultSet.close() tan pronto como sea posible para liberar la memoria.

Le recomiendo encarecidamente que siga el segundo capítulo de este tutorial ("Procesando Sentencias SQL").