sql >> Databáze >  >> RDS >> Mysql

Jak správně zvládnout zablokování InnoDB v Javě/JDBC?

Váš kód je v podstatě správný. Výjimka vyvolaná při zablokování je SQLException . Výjimka je getSQLState() metoda poskytuje chybový kód, který poskytuje další informace o skutečné chybě.

Mezi jednotlivými pokusy byste také měli chvíli počkat, abyste příliš nezatížili server.

Jak jste chytře uhodli, nastavte maximální počet pokusů, jinak se můžete dostat do nekonečné smyčky.

Konečný kód by mohl vypadat takto:

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

Je zřejmé, že výše uvedený kód není optimální. Možná budete chtít rozlišit chyby, ke kterým dochází v době připojení, a chyby v době provádění. Můžete také zjistit, že po některých chybách je malá naděje, že další pokus bude fungovat (např. nesprávné přihlašovací údaje nebo chyba syntaxe SQL).

Ptali jste se na spoustu otázek, ale pokusím se na všechny odpovědět:

Ano, viz výše:SQLException 's jsou ty, přičemž další informace poskytuje getErrorCode() nebo getSQLState() .

SQLException mohl být vyvolán prakticky všemi metodami všech tříd z java.sql balíček.

Ano, viz výše.

Samozřejmě nesmíte znovu vytvářet PreparedStatement mezi dvěma dotazy. Před voláním executeQuery() stačí nastavit nové hodnoty parametrů znovu. Samozřejmě, pokud potřebujete provést další dotaz, pak nový PreparedStatement je vyžadováno.

A (nový) ResultSet objekt vrací Statement.executeQuery() , který představuje výsledek dotazu. Sami takový objekt nikdy nevytvoříte. V ideálním případě zavoláte ResultSet.close() co nejdříve, abyste uvolnili paměť.

Důrazně vám doporučuji sledovat druhou kapitolu tohoto návodu ("Zpracování příkazů SQL").




  1. Přechod z MySQL na PostgreSQL - tipy, triky a problémy?

  2. Jak SQL Server rozhodne o formátu pro implicitní převod data a času?

  3. Ukládání statistických dat, potřebuji DECIMAL, FLOAT nebo DOUBLE?

  4. Nelze resetovat heslo uživatele root pomocí --skip-grant-tables na ubuntu 16