3

複数のコンピューターで実行される Java アプリがあり、それらはすべて同じ MySQL データベースに接続します。データベースが正しく更新されていることを確認するには、トランザクションが必要です。

ロックの解除に問題があります。コードは次のとおりです。

public boolean bookSeats(int numeroSala, Calendar dataOra, List<Posto> posti) {
    JDBConnection connection = JDBConnection.getDbConnection();
    Connection conn = connection.conn;
    java.sql.Date javaSqlDate = new java.sql.Date(dataOra.getTime().getTime());
    java.sql.Time javaSqlTime = new java.sql.Time(dataOra.getTime().getTime());

    try {
        conn.setAutoCommit(false);
        conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
    } catch (SQLException e) {
        e.printStackTrace();
    }

    try
    {
        Posto p = null;
        ListIterator<Posto> itr = posti.listIterator();
        PreparedStatement stmt = null;
        stmt = conn.prepareStatement(
            "INSERT INTO sala?_tickets " + 
            "(giornoSpettacolo, orarioSpettacolo, fila, posto) " + 
            "VALUES (?, ?, ?, ?)");

        stmt.setInt(1, numeroSala);
        while(itr.hasNext())
        {
            p = itr.next();
            stmt.setString(2, javaSqlDate.toString()); // giornoSpettacolo
            stmt.setString(3, javaSqlTime.toString()); // orarioSpettacolo
            stmt.setInt(4, p.getFila()); // fila
            stmt.setInt(5, p.getNumero()); // posto
            stmt.addBatch();
        }

        stmt.executeBatch();

        conn.commit();
        return true;
    }
    catch (SQLException e) {
        e.printStackTrace();
    }

    return false;
}

この方法は正常に機能しますが、これを別のコンピューターで同時に実行しようとすると、conn.commit()完了したにもかかわらず DEADLOCK エラーが発生します。

最初のアプリケーションを閉じるとすぐに、他のアプリケーションはデッドロック エラーなしでメソッドを実行できます。COMMIT でロックが解除されないようです。

4

4 に答える 4

3

SERIALIZABLEについてのMySQLのドキュメントによると:

このレベルは REPEATABLE READ に似ていますが、自動コミットが無効になっている場合、InnoDB はすべての単純な SELECT ステートメントを暗黙的に SELECT ... LOCK IN SHARE MODE に変換します。

コミット後に自動コミットを再度有効にするか、接続を試してみてください。代わりに REPEATABLE_READ。

于 2012-05-11T01:41:11.160 に答える
1

ベア JDBC でトランザクションを実行する方法については、このドキュメントを参照できます。それが役に立てば幸い。

于 2012-05-11T01:38:21.550 に答える
0

はい、最初の答えが言うように接続を閉じます。ただし、さらに、上記のコードを「同期化された」メソッドに入れることができる場合は、一度に1つのスレッドのみがアクセスできるようになります。

それとは別に、JDBCでのデッドロック処理について説明している次のリンクをご覧ください。

Javaでのデッドロック検出

于 2012-05-11T07:19:23.150 に答える
0

メソッドで使用されるすべてのリソースが確実に解放されるようconn.close()に、ブロック内で常に a を実行する必要があります。finally

于 2012-05-11T01:40:53.597 に答える