web-dev-qa-db-ja.com

接続が不良になったときにJBoss接続プールをOracleに再接続する方法はありますか?

JBossとOracleは別々のサーバー上にあります。接続が切断されたようで、JBossで問題を引き起こしています。接続が最初にドロップされている理由を理解しているときに、接続が悪い場合、JBossをOracleに再接続するにはどうすればよいですか?

31
Joshua

通常、プールには構成オプションがあり、借用時に検証クエリを実行できます。検証クエリが正常に実行されると、プールはその接続を返します。クエリが正常に実行されない場合、プールは新しい接続を作成します。

JBoss Wiki には、プールのさまざまな属性が記載されています。

<check-valid-connection-sql>select 1 from dual</check-valid-connection-sql>

それはトリックを行う必要があるようです。

27
Steve K

古い「select 1 from dual」トリックを使用できますが、これの欠点は、プールから接続を借りるたびに追加のクエリを発行することです。大量の場合、これは無駄です。

JBossは、Oracleで使用する必要のある特別な接続バリデーターを提供します。

<valid-connection-checker-class-name>
    org.jboss.resource.adapter.jdbc.vendor.OracleValidConnectionChecker
</valid-connection-checker-class-name>

これは、Oracle JDBC接続クラスの独自のping()メソッドを利用し、ドライバの基盤となるネットワークコードを使用して、接続がまだ有効かどうかを判断します。

ただし、接続を借用するたびにこれを実行するのは依然として無駄です。そのため、バックグラウンドスレッドがプール内の接続をチェックし、停止した接続を自動的に破棄する機能を使用することができます。これははるかに効率的ですが、接続doが停止した場合、バックグラウンドスレッドがチェックを実行する前にそれらを使用しようとすると失敗します。

バックグラウンドチェックの設定方法については、 wiki docs を参照してください(background-validation-millis)。

33
skaffman

コメントの担当者が不足しているため、回答の形式になっています。 'Select 1 from dual'とskaffmanのorg.jboss.resource.adapter.jdbc.vendor.OracleValidConnectionCheckerメソッドは同等ですが、接続チェックはある程度の抽象化を提供します。トラブルシューティングのためにOracle jdbcドライバーを逆コンパイルする必要があり、pingのOracleの内部実装は'Select 'x' from dual'。ナッチ。

9
abh

JBossは接続を検証する2つの方法を提供します:-PingベースAND-クエリベース

要件に応じて使用できます。これは、データソース構成ファイルで定義された期間ごとに別のスレッドによってスケジュールされます。

_<background-validation>true</background-validation> <background-validation-minutes>1</background-validation-minutes>
_

Jbossに適切なOracleドライバーがない場合、クラスキャストまたは関連エラーが発生し、その接続が接続プールからドロップアウトを開始することがあります。 _org.jboss.resource.adapter.jdbc.ValidConnectionChecker_インターフェースを実装して、独自のConnectionValidatorクラスを作成してみることができます。このインターフェイスは、単一のメソッド 'isValidConnection()'のみを提供し、有効な接続の代わりに 'NULL'を予期します。

例:

_public class OracleValidConnectionChecker implements ValidConnectionChecker, Serializable {

   private Method ping;

   // The timeout (apparently the timeout is ignored?)
   private static Object[] params = new Object[] { new Integer(5000) };

   public SQLException isValidConnection(Connection c) {

       try {
           Integer status = (Integer) ping.invoke(c, params);

           if (status.intValue() < 0) {
               return new SQLException("pingDatabase failed status=" + status);
           }

       }
       catch (Exception e) {
           log.warn("Unexpected error in pingDatabase", e);
       }

       // OK
       return null;
   }
}
_
6
arviarya

最近、孤立したOracle DBMS_LOCKセッションロックが原因でクライアント側の接続プールに無期限に保持される、フローティングリクエスト処理の失敗が発生しました。

したがって、30分でセッションの有効期限を強制するが、アプリケーションの操作には影響しないソリューションは次のとおりです。

<check-valid-connection-sql>select case when 30/60/24 > sysdate-LOGON_TIME then 1 else 1/0 end 
from V$SESSION where AUDSID = userenv('SESSIONID')</check-valid-connection-sql>

これには、プールから接続を取得するプロセスの速度低下が含まれる場合があります。負荷がかかっている状態でこれをテストしてください。

3
Vadzim

@skaffmanの回答を少し更新しました。 JBoss 7では、有効な接続チェッカーを設定するときに「class-name」属性を使用する必要があり、パッケージも異なります。

<valid-connection-checker class-name="org.jboss.jca.adapters.jdbc.extensions.Oracle.OracleValidConnectionChecker" />

2
Jakub Godoniuk