4

次のような DB2 テーブルを更新しています (Java コード):

// Some code  ripped out for brevity...
sql.append("UPDATE " + TABLE_THREADS + " ");
sql.append("SET STATUS = ? ");
sql.append("WHERE ID = ?");

conn = getConn();
pstmt = conn.prepareStatement(sql.toString());
int idx1 = 0;
pstmt.setInt(++idx1, status);
pstmt.setInt(++idx1, id);
int rowsUpdated = pstmt.executeUpdate();
return rowsUpdated;

しばらくすると、ロールバックとエラー メッセージが表示されます。

UNSUCCESSFUL EXECUTION CAUSED BY DEADLOCK OR TIMEOUT. REASON CODE 00C9008E, TYPE OF RESOURCE 00000302, AND RESOURCE NAME SOME.THING.X'000002'. SQLCODE=-913, SQLSTATE=57033, DRIVER=3.57.82

エラー -913のドキュメントには、この REASON CODE はタイムアウトであることを意味すると書かれています。リソース タイプ 00000302 はテーブル スペース ページで、リソース名がまったくわかりません。

SQL を単独で実行すると、正常に動作します。

UPDATE MY.THREADS
SET STATUS = 1
WHERE ID = 156

SELECTステータスが更新されていることがわかります。(ただし、タイムアウト前の長い待機期間中にこのSQLを実行すると、同じ問題が発生します。永遠に時間がかかり、キャンセルするだけです)。

トランザクションでいくつかのことが起こっていますが、このテーブルまたはレコードに対する他の更新は見られません。テーブルには作成/削除トリガーがありますが、更新トリガーはありません。カーソルを使用した選択や、奇妙な分離レベルの変更は見られません。これを引き起こすトランザクションは他にあまり見られません。

このエラーが発生するのはなぜですか? トランザクションで他に何を探す必要がありますか?


編集:

リクエストの最初から「スタック」する場所まで、コードをステップ実行しました。2 つの DAO があり、両方がトランザクションを作成しているように見えます。それが問題かもしれないと思います。

4

2 に答える 2

3

自分の質問に答えて申し訳ありませんが、問題が見つかりました。これは、DAO が自身の接続を追跡する、やや自家製のフレームワークです。

conn = getConn();

これにより、明示的なトランザクション中に各 DAO メソッドに対して同じ接続が返されます。

コードをステップ実行しているときに、トランザクションで呼び出していたメソッドが新しいトランザクション、新しい DAO、したがって新しい DB 接続を作成していることがわかりました。これで、2 つのトランザクションが開かれ、2 つの接続が確立されました。この時点で、私が実際に行き詰まりを迎えていることが容易にわかります。

以前に取り組んだアプリではネストされたトランザクションが許可されていたので、これには少し驚きました。(両方のトランザクションに同じ DB 接続を使用)

于 2013-05-14T14:01:13.723 に答える