Mysql
 sql >> Base de données >  >> RDS >> Mysql

Comment gérer correctement les interblocages InnoDB en Java/JDBC ?

Votre code est essentiellement correct. L'exception déclenchée lorsqu'un blocage se produit est une SQLException . L'exception getSQLState() méthode fournit renvoie un code d'erreur qui fournit informations complémentaires sur l'erreur réelle.

Vous devez également attendre un peu de temps entre les tentatives, afin de ne pas trop charger votre serveur.

Comme vous l'avez intelligemment deviné, définissez un nombre maximum de tentatives, sinon vous risquez de vous retrouver dans une boucle infinie.

Le code final pourrait ressembler à ceci :

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

De toute évidence, le code ci-dessus est sous-optimal. Vous pouvez différencier les erreurs qui se produisent au moment de la connexion et les erreurs au moment de l'exécution. Vous pouvez également détecter qu'après certaines erreurs, il y a peu d'espoir qu'une autre tentative fonctionne (par exemple, de mauvaises informations d'identification ou une erreur de syntaxe SQL).

Vous avez posé beaucoup de questions, mais je vais essayer d'y répondre :

Oui, voir ci-dessus :SQLException sont ceux, avec plus d'informations fournies par getErrorCode() ou getSQLState() .

Une SQLException pourrait être lancé par pratiquement toutes les méthodes de toutes les classes de java.sql paquet.

Oui, voir ci-dessus.

Évidemment, vous ne devez pas recréer un PreparedStatement entre deux requêtes. Il vous suffit de définir de nouvelles valeurs pour vos paramètres avant d'appeler executeQuery() de nouveau. Bien sûr, si vous devez exécuter une autre requête, alors un nouveau PreparedStatement est requis.

Un (nouveau) ResultSet l'objet est retourné par Statement.executeQuery() , qui représente le résultat de la requête. Vous ne créez jamais un tel objet vous-même. Idéalement, vous appellerez ResultSet.close() dès que possible pour libérer de la mémoire.

Je vous conseille vivement de suivre le deuxième chapitre de ce tutoriel ("Traitement des instructions SQL").