sql >> データベース >  >> RDS >> Mysql

Java / JDBCでInnoDBデッドロックを適切に処理するにはどうすればよいですか?

    あなたのコードは本質的に正しいです。デッドロックが発生したときに発生する例外は、SQLExceptionです。 。例外のgetSQLState() メソッドprovidesは、追加情報 実際のエラーについて。

    また、サーバーに過度の負荷をかけないように、試行と試行の間に短時間待つ必要があります。

    巧妙に推測したように、最大​​試行回数を設定してください。そうしないと、無限ループに陥る可能性があります。

    最終的なコードは次のようになります:

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

    明らかに、上記のコードは最適ではありません。接続時に発生するエラーと実行時に発生するエラーを区別したい場合があります。また、いくつかのエラーの後、別の試行が機能する可能性はほとんどないことを検出することもできます(たとえば、間違ったクレデンシャルやSQL構文エラー)。

    あなたはたくさんの質問をしましたが、私はそれらすべてに答えようとします:

    はい、上記を参照してください:SQLException は、getErrorCode()によって提供される詳細情報を備えたものです。 またはgetSQLState()

    SQLException java.sqlのすべてのクラスの事実上すべてのメソッドによってスローされる可能性があります パッケージ。

    はい、上記をご覧ください。

    もちろん、PreparedStatementを再作成してはなりません。 2つのクエリの間。 executeQuery()を呼び出す前に、パラメータに新しい値を設定する必要があります。 また。もちろん、別のクエリを実行する必要がある場合は、新しいPreparedStatement が必要です。

    (新しい)ResultSet オブジェクトはStatement.executeQuery()によって返されます 、クエリの結果を表します。このようなオブジェクトを自分で作成することはありません。理想的には、ResultSet.close()を呼び出します。 できるだけ早くメモリを解放してください。

    このチュートリアル の第2章に従うことを強くお勧めします。 (「SQLステートメントの処理」)。




    1. plpgsqlを介してPostgresからテーブルの主キーを取得するにはどうすればよいですか?

    2. SalesforceでSQLServerを使用するためのヒント

    3. SQL:値がnullの場合にのみ、列の値を更新するにはどうすればよいですか?

    4. Connector / C ++ MySQLエラーコード:2014、SQLState:HY000およびコマンドの同期エラーはなぜですか?