1

GlassFish 3.1 (ビルド 43) サーバーで実行されている古い Web ベースのアプリケーション (Spring 2.5.4 フレームワークを使用した Java) があります。このアプリケーションは最近 (数週間前)、Oracle 11g (11.2.0.3.0) データベースと ojdbc6.jar/orai18n.jar (Oracle 10g 10.2.0.3.0 および ojdbc14.jar から) を使用するようにリダイレクトされました。 - JDBC シン接続を使用します。アプリケーションは接続に org.apache.commons.dbcp.BasicDataSource バージョン 1.2.2 を使用しており、データベース リクエストは Spring jdbcTemplate (JdbcDaoSupport 抽象クラスを介して) または Spring の PlatformTransactionManager を介して処理されます。

今朝、アプリケーション ユーザーが情報を入力して変更し、後でアプリケーションを介してそのデータを取得して印刷できることを確認しましたが、過去 24 時間にコミットされた更新はありませんでした。このアプリケーションには現在、毎日数人のユーザーしかいません。彼らは明らかに、前日に接続プールによって開かれた同じ接続を共有しているため、コミットされていない更新はアプリケーションを通じて表示されましたが、データベースへの他の接続を通じては表示されませんでした。 . 接続が閉じられると、コミットされていない更新が失われました。

サーバー ログを調べたところ、データベースに変更が最後にコミットされた時刻から、翌朝印刷されたレポートの時刻まで、エラーは示されませんでした。さらに、JDBC 接続が Auto-Commit false に設定された状態で (何らかの方法で) 変更が行われた場合でも、トランザクションの一部である更新の一部に対して特定のコミットが行われました。 /catch ブロックは、「transactionManager.commit(transactionStatus);」のいずれかを実行する必要があります。または「transactionManager.rollback(transactionStatus);」エラーなしで処理されたはずの呼び出し。コミットが正常に返されたように見えますが、実際にはコミットは行われませんでした。

GlassFish ドメインとアプリケーションを再起動すると、さまざまな更新が入力されたときにコミットされ、通常の操作が復元されました。

私の質問は、このようなことが起こっているのを見たり聞いたりした人はいますか?もしそうなら、何が原因でしたか?

ここでのアイデアに感謝します-私たちは途方に暮れています。


いくつかの新しい情報:

  1. Oracle 11g サーバーを調査したところ、コミットが停止したように見える頃に、完全に解決できなかった他の操作で 4 つの操作がブロックされていたことがわかりましたが、おそらく更新でした。

  2. Glassfish サーバーのログを調べたところ、この推定開始時刻に続いてワーカー スレッドの外観が変化し、1 つのスレッドのみが数時間使用され続けるまで、ログに表示されるスレッドが少なくなったことが示されました。

  3. 問題は約 1 週間後に再び発生し、約 1/2 時間後に発見されました。この時点で、2 つのワーカー スレッドが動作していました。

4

1 に答える 1

0

この問題は、2 つの組み合わせが原因で発生しました。1 つ目は、Spring トランザクションをセットアップするメソッドでしたが、TransactionManager.commit() と TransactionManager.rollback() (およびトランザクションを構成するいくつかの SQL 要求) の両方をバイパスする出口がありました。これは確かに間違ったコーディングでしたが、過去には、このトランザクションはクローズされたため、その後の使用には影響しませんでした。

解決策は、何もすることがない場合にトランザクションが開始されないようにすることでした。または、一般に、開始されたすべてのトランザクションが完了していることを再確認します。

この問題がどのように、またはなぜ発生し始めたのかについては、正確にはわかりません。そのため、以下は部分的に推測されています。どうやら、Oracle 11g へのアップグレードおよび/または ojdbc6.jar ドライバーへの切り替えにより、誤ったコードの以前の動作が変更されたため、トランザクションは終了せず、接続の自動コミットは false のままでした。(上記の特殊なケースはめったに発生しないため、特定していない他の変更が原因である可能性もありますが、実際に発生します。) 対応する JDBC 接続は、特定の GlassFish ワーカー スレッドにバインドされているようです (これを「悪い」と呼びます)。通常動作する「良い」スレッドとは対照的に、以下のスレッド)。この「不良」スレッドが (この特定のアプリケーションの) アプリケーション要求を処理するために使用されると、変更はコミットされず、select はダーティ データを返します。時間が経つにつれて、「正常な」スレッドで変更が要求され、JDBC 接続が「不良な」スレッドでコミットされていない変更が既に行われている場合、新しい要求がハングし、ワーカー スレッドもハングします。最終的に、「悪い」ワーカー スレッド以外はすべてハングし、アプリケーションの観点からはすべてが正しく動作しているように見えますが、何もコミットされません。

繰り返しますが、解決策は悪いコードを修正することでした。

于 2013-11-13T13:19:20.363 に答える