Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Jak prawidłowo obsłużyć zakleszczenia InnoDB w Java/JDBC?

Twój kod jest zasadniczo poprawny. Wyjątkiem zgłaszanym w przypadku wystąpienia zakleszczenia jest SQLException . getSQLState() wyjątku metoda zapewnia zwraca kod błędu, który zapewnia dodatkowe informacje o rzeczywistym błędzie.

Powinieneś także odczekać krótką chwilę między próbami, aby nie obciążać zbytnio serwera.

Jak sprytnie zgadłeś, ustaw maksymalną liczbę prób lub możesz skończyć w nieskończonej pętli.

Ostateczny kod może wyglądać tak:

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

Oczywiście powyższy kod nie jest optymalny. Możesz chcieć odróżnić błędy występujące w czasie połączenia i błędy w czasie wykonywania. Możesz również wykryć, że po niektórych błędach nie ma nadziei, że kolejna próba zadziała (np. błędne dane uwierzytelniające lub błąd składni SQL).

Zadałeś wiele pytań, ale postaram się odpowiedzieć na wszystkie:

Tak, patrz wyżej:SQLException 's są tymi, a więcej informacji dostarcza getErrorCode() lub getSQLState() .

SQLException może zostać wyrzucony przez praktycznie wszystkie metody wszystkich klas z java.sql pakiet.

Tak, patrz wyżej.

Oczywiście nie możesz ponownie utworzyć PreparedStatement między dwoma zapytaniami. Musisz tylko ustawić nowe wartości swoich parametrów przed wywołaniem executeQuery() ponownie. Oczywiście, jeśli musisz wykonać inne zapytanie, to nowy PreparedStatement jest wymagane.

A (nowy) ResultSet obiekt jest zwracany przez Statement.executeQuery() , który reprezentuje wynik zapytania. Sam nigdy nie tworzysz takiego obiektu. Idealnie zadzwonisz ResultSet.close() tak szybko, jak to możliwe, aby zwolnić pamięć.

Gorąco radzę zapoznać się z drugim rozdziałem tego samouczka („Przetwarzanie instrukcji SQL”).




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Klejnot MySQL2 Ruby nie zainstaluje 10.6

  2. ActiveRecord::ConnectionTimeoutError:nie można uzyskać połączenia z bazą danych w ciągu 5000 sekund (czekano 5000 sekund)

  3. Utwórz funkcję z opcjonalnymi argumentami w MySQL

  4. Dlaczego muszę użyć podwójnej ucieczki (użyj 4 \), aby znaleźć ukośnik odwrotny ( \ ) w czystym SQL?

  5. W jaki sposób umożliwiasz klientom używanie ich openid w Twojej witrynie, podobnie jak stackoverflow?