• 締切済み

DBCPで、DB切断後のコネクション取得

struts1.3 + spring1.2 + tomcat + oracleで開発中です。 DBCPでコネクションがプーリングされた状態で、DBが停止・再起動 した場合、DB停止前からプーリングされていたコネクションは 無効になってしまいますが、これの対処はどうするのがベストでしょうか。 (1) testOnBorrow で検査する →コネクション取得の都度発行される検査用SQLの負荷が心配 (2) testWhileIdle で検査する。 →検査スレッドの起動間隔はどれくらいが適当なのか? (3) getConnection時に自前でリトライするロジックを組み込む →WebSphereにある、StaleConnectionExceptionのような例外がある? (4) もっと別の画期的な方法がある!! 以上、よろしくお願いします。

  • Java
  • 回答数1
  • ありがとう数2

みんなの回答

  • ecogilis
  • ベストアンサー率60% (12/20)
回答No.1

こんちわ。 だいぶ昔のことなので忘れてるんですが。。。 そもそもにDBCPが汎用のプールだし、汎用だからJDBCだけを利用してると思うんですが、JDBCのAPIとしてコネクションが有効か否かを検査する術がないので。。。(今はちがう?)。 (1)確実なのはこれだと思います。負荷はちょっとあるでしょうけどシビアなパフォーマンス要件や環境でなければ普通はまともなパフォーマンス、軽微な負荷程度なのではないかと思うです。DBCPの実装が不明なんですが、validationQueryは固定SQLなのでSQLキャッシュもされてパース負荷も少ないでしょうし、行を読まなければ負荷もSQLのパースとかそんな程度のものだろうし。いや1行は必要なのか。。。でもDUAL表を使えばディスクアクセスもないから。やっぱり負荷は少ないんじゃないでしょうか。 ちなみにある案件ではこれを利用しても結構快適でした。 (2)は、ためすしかないんじゃないでしょうか。(1)をやっとけば気にする必要なしとも思います。 (3)は、あったっけ。。。ないんじゃないでしょうか。ちなみにWebSphereではStaleはSQLのexecute時に発生すると記憶してます。getConnection時にはでないようなー。 (4)あったらいいなぁ(w。DB固有のコネクションプールをつかうとか。OracleならそれこそDBCPの代わりみたいなのありそうですけど。。。ないんすかね。

aj4all
質問者

お礼

ご回答ありがとうございます。 (1)・・・なるほど、キャッシュもあるしDUAL表を使えば問題なさそうですね。 (3)・・・IBMのサイトに以下の例が載っていますので、StaleConnectionExceptionは、getConnection時に返るものと思われます。 try {  conn = dataSource.getConnection(user, password);   :  (connを使用したSQL処理)   :  i = 0;             // リトライのためのカウンターを0にする } catch (StaleConnectionException scex) {  // Stale Connection を catch  if (conn != null) {   try {    conn.close();       // Stale Connection を close   } catch (Exception e) {    e.printStackTrace();   }  } } catch (Exception e) {   : (4)・・・OracleConnectionPoolDataSourceなるものがあるようですね。これに再接続の機能があればよいのですが。 調べてみます。 ありがとうございました。

関連するQ&A

  • DB2のJDBCを使用したDBコネクションの取得方法の違い

    WebSphereとDB2を使用してDB2へアクセスしてテーブルからデータの取得をしたいと思っています。 このとき、DB2のJDBCを使用しますが、getConnectionでコネクションを取得するときに指定するDBのURLに、複数の指定方法があるようです。 その1: jdbc:db2:データベース名 その2: jdbc:db2://ホストIP:ポート番号/データベース名 その1の方法ではコネクションを取得できたのですが、その2の方法では失敗しました。 ホストIPには自分のマシンのIPを、ポート番号にはDB2をインストールしたときに設定した番号を指定しました。 この両者の違いをご存知の方は教えてください。 また、その2の方法でなぜ失敗したのか、見当がつく方がいたらこちらも教えていただきたいと思います。 なお、実行環境は以下の通りです。 CPU ペンティアム3 800Mhz メモリ 512MByte OS Windows2000 SP2 ブラウザ IE5.5 SP2 AS Websphere 4.0 DB DB2 7.2 ※WebshpereとDB2は同一マシンにインストールされています。

    • ベストアンサー
    • Java
  • コネクションプーリングの枯渇

    tomcat-Servletでの開発を行っています。 MVCモデルでのWEBアプリケーションです。 DBへの接続用として自作のコネクションプーリングを使用しています。 (プーリング数は20を設定) 基本的なSQL実行フローは下記のようになります。 1.コネクションプーリングを取得 2.SQL文を実行 3.コネクションプーリングを返却 ところが、時間を置いて psコマンドで確認すると、 だんだん数が減っていっているようです。 原因を調査しているのですが、 もし次のような原因で正しいかどうか分かりましたらご連絡ください。 <考えている原因> 要するに上記の3(返却)がされていないのであって。 ・実行処理中に利用者がクライアント側のブラウザを落としている。 と仮説を立てているのですが。 この仮説が正しいかどうか、 また、もし正しい場合には、どうすれば回避可能かをご教授ください。 補足の必要があればご連絡ください。 (コネクションプーリングの全文を載せたいのですが、  長すぎるようで・・・)

    • ベストアンサー
    • Java
  • DBのコネクション取得で、無応答状態になってしまう。

    こちらに、投稿していいのかわからないのですが・・・。 以下のような現象が発生し、原因究明に苦慮してます。 原因に心当たりのある方、よろしくお願いします。 #スレッドダンプも載せてみました、インターネットで勉強しながら #たどたどしく、取得したものです。 <現象> DBのコネクション取得で、無応答状態になってしまう。 <環境> JBOSS 3.2.1 PostgresSQL7.4.1 JDK1.4.2_03 JakartaCommonsDBCP1.1 <スレッドダンプ> Full thread dump Java HotSpot(TM) Server VM (1.4.2_03-b02 mixed mode): "PoolThread-54" prio=1 tid=0x0812fbc0 nid=0x38eb waiting for monitor entry [927fe000..927fee18] at org.apache.commons.dbcp.AbandonedObjectPool.borrowObject(AbandonedObjectPool.java:111) - waiting to lock <0x4dcc79b0> (a org.apache.commons.dbcp.AbandonedObjectPool) at org.apache.commons.dbcp.PoolingDataSource.getConnection(PoolingDataSource.java:110) at org.apache.commons.dbcp.BasicDataSource.getConnection(BasicDataSource.java:312)   ・   ・ "PoolThread-53" prio=1 tid=0x08514810 nid=0x38eb in Object.wait() [926fe000..926fee98] at java.lang.Object.wait(Native Method) - waiting on <0x491399e0> (a org.mortbay.util.ThreadPool$PoolThread) at org.mortbay.util.ThreadPool$PoolThread.run(ThreadPool.java:450) - locked <0x491399e0> (a org.mortbay.util.ThreadPool$PoolThread) よろしくお願いします。

  • MySQL・Tomcat・JSP 何度もSubmit実行すると、SQLNestedExceptionエラー

    現在、社内で勉強がてら、社内用アプリケーションを開発しております。 環境は以下です。 ・Windows2003ServerR2 ・Apache2.2.11 ・Tomcat6 ・MySQL5.1 ・Java1.6 フレームワークを使わずに、JSP/サーブレットで開発しております。 submitして、ブラウザの「戻る」を何度も繰り返したりして DB接続するサーブレットを何度も実行すると 「SQLNestedException」エラーになり、 サーバーリブート(もしくはtomcat/mysqlサービス再起動) しない限り、アプリに接続できなくなってしまいます。 tomcatのstdout.logには、以下が出力されております。 -------------------------------------------------------↓ org.apache.tomcat.dbcp.dbcp.SQLNestedException: Cannot get a connection, pool error Timeout waiting for idle object at org.apache.tomcat.dbcp.dbcp.PoolingDataSource.getConnection(PoolingDataSource.java:104) at org.apache.tomcat.dbcp.dbcp.BasicDataSource.getConnection(BasicDataSource.java:880) ・ ・ ・ -------------------------------------------------------↑ connectionのclose()をすれば良いようなことが、 ネットで調べてあったのですが、 射た感じの情報が 見つからなかったので、投稿させていただきました。 SJC-Pのバージョン5.0を取ってはいますが、 元々NotesDominoの開発が長く、JSPは初心者で、 申し訳ありません。 ご教示いただけるとありがたいです。 【補足】 すみません。try{}catchのcatch側に、close()を入れてませんでした。 しかし、close()を入れてないからといってサーバリブート(サービスリブート)しないかぎり、鍵が開けられないような感じになっているのは なんか変ですね。 引き続き調べてみますが、解る方いらっしゃいましたら、よろしくお願いいたします。 他力本願かもですが、生産性向上思考で、情報ご提供お願いいたします。

  • java log4jの環境設定

    調べてみたのですが、参考になるページが見当たらなかったので(私が理解できなかっただけかもしれませんが。。) ご質問させていただきます。 表題の件です。javaのサーブレットを用いてログ出力する為にlog4jを使用しています。 そのため、log4j.xmlにファイルの出力先やらなんやらを記述しています。(これが通常だと思います) tomcatのWEBアプリケーションパッケージですので、DB接続等の設定は「META-INF/context.xml」に記述(Javaアプリ側で名前解決してDatasourceとして取得)しています。 上記からDB接続情報、ログの出力先情報はそれぞれ別ファイル(XML)から取得していますが、環境依存する値なので、編集するならひとつのファイルから行いたいです。 できれば、log4jのファイル出力先情報等をcontext.xmlにて記述して解決したいです。 (理由:tomcat6/servlet2.5を使用しており、tomcat6のdbcpを使用してコネクションプーリングしている為、DB接続の方法は変更したくない為) 以上、ご存知の方ご教授お願いできますでしょうか。

    • ベストアンサー
    • Java
  • コネクションプールについて

    コネクションプール有とコネクションプール無でDB接続・切断を繰り返したときに どれくらい差があるか試してみようと思いWebアプリ上(フレームワークにStruts2を使用)で 下記コードを実行してみました。 dbcpConnectメソッド(コネクションプール有) と jdbcConnectメソッド(コネクションプール無) をそれぞれ千回づつループで回して実行してみました。 結果は 【コネクションプール有】実行にかかった時間:157384 ミリ秒 【コネクションプール無】実行にかかった時間:158760 ミリ秒 で大差はありませんでした。 コネクションプールを使用するともう少し早いと思っていたのですがそのようなことはないのでしょうか。 public String test4() { // コネクションプール有の接続 long start = System.currentTimeMillis(); for(int i=0; i< 1000; i++) { dbcpConnect(); } long stop = System.currentTimeMillis(); System.out.println("実行にかかった時間は " + (stop - start) + " ミリ秒です。"); // コネクションプール無の接続 start = System.currentTimeMillis(); for(int i=0; i< 1000; i++) { jdbcConnect(); } stop = System.currentTimeMillis(); System.out.println("実行にかかった時間は " + (stop - start) + " ミリ秒です。"); return "jstl4"; } public void dbcpConnect() { Connection con = null; try{ Context context = new InitialContext(); //DataSource ds = (DataSource)context.lookup("java:comp/env/jdbc/library"); DataSource ds = (DataSource)context.lookup("java:/comp/env/jdbc/dhcpTest"); con = ds.getConnection(); Statement stmt = con.createStatement(); String sql = "SELECT * FROM test.test"; ResultSet rs = stmt.executeQuery(sql); } catch(Exception e) { System.out.println("Error"); } finally { try { con.close(); } catch (SQLException e) { e.printStackTrace(); } } } public void jdbcConnect() { Connection con = null; try{ con = DriverManager.getConnection("jdbc:mysql://localhost", "root", "root"); Statement stmt = con.createStatement(); String sql = "SELECT * FROM test.test"; ResultSet rs = stmt.executeQuery(sql); } catch(Exception e) { System.out.println("Error"); } finally { try { con.close(); } catch (SQLException e) { e.printStackTrace(); } } }

    • ベストアンサー
    • Java
  • DB接続について

    JAVA初心者です。 DB接続についてなのですが、いままで設定ファイルより<url>,<user>,<password>等の情報を取得してDB接続していたのですが、今後、『WebSphere』のデータソースの設定から取得する方式に変更となり、プログラム例として次のコードをもらったのですが… InitialContext ctx = new InitialContext(); DataSource ds = (DataSource)ctx.lookup("登録したJNDI名"); Connection conn = ds.getConnection(); これを以下のコードにどう組み込んでよいかわかりません… どうかご教授お願いします。 public class ConnectionCache{ private static final string This_Name = "jp.co.ise.filetransfer.server.common.ConnectionCache"; private static ConnectionCache instance = null; private static ObjectPool pool = null; private DataSource ds = null; // java.lang.Object#Object() private ConnectionCache(){} // Method ConnectionCache // @param ds private ConnectionCache(DataSource ds){ this.ds = ds; } // Method getDataSource // @return DataSource public static DataSource getDataSource(){ return instance.ds; } public static void init(Properties prop) throws Exception { try { class.formName(prop.getProperty("drive")); // プールするアイドルコネクション数の上限 int maxIdleNum = Integer.parselnt(prop.getProperty("maxIdle")); // プール初期化時のアイドルコネクション数 int initIdleCapacityNum = Integer.parselnt(prop.getProperty("initIdleCapacity")); // ObjectPoolインスタンスを生成 int initIdleCapacityNum = Integer.parselnt(prop.getProperty("initIdleCapacity")); // Connectionオブジェクトを生成するためのConnectionFactoryインスタンスの生成 ConnectionFactory conFactory = new DriverManagerConnectionFactory( prop.getProperty("url"), prop.getProperty("user"), prop.getProperty("password") ); // PoolableConnectionFactoryインスタンスの生成 new PoolableConnectionFactory( conFactory, pool, null, prop.getProperty("validationQuery"), true, true ); // プーリング機能を持つDataSourceインスタンスの生成 DataSource ds = new PoolingDataSource(pool); // 初期サイズ指定分のコネクションをプール ArrayList initConnections = new ArrayList(); // 新規接続 for(int i = 0; i < initIdleCapacityNum; i++){ initConnections.add(ds.getConnection()); } // プールへ返却 for(int i = 0; i < initIdleCapacityNum; i++){ ((Connection)initConnections.get(i)).close(); } instance = new AppleConnectionCache(ds); system.out.println( THIS_NAME + "DB接続プールを初期化しました。:プール内のコネクション数 = " + pool.getNumIdle()); } catch (Throwable t) { throw new Exception ( THIS_NAME + "DB接続プールの初期化に失敗しました。:" + t.getMessage()); } } //Method getInstance. //@return AppleConnectionCache public static synchronized AppleConnectionCache getInstance() { return instance; } //Method getConnection. //@return Connection public synchronized Connection getConnection() throws Exception { Connection conn = null; try{ conn = ds.getConnection(); } catch (SQLException e) { throw new Exception ( THIS_NAME + "DB接続に失敗しました。:" + e.getMessage()); } return conn; } //Method closeCache. public synchronized void closeCache() { try{ pool.close(); system.out.println(THIS_NAME + "DB接続プールのリソースを開放しました。"); } catch (Exception e) { } }

  • Tomcat6のコネクションプーリングについて

    Tomcat6のコネクションプーリングについて 現在、以下の環境で開発を行っているのですが、 データソースからConnectionを取得できていない状況です。 過去に同様の内容が記載されていたのですが、 内容が理解できず投稿させていただいております。 【フォルダ構成】 test  |  |--META-INF  |   |  |   --context.xml  |  |--WEB-INF     |      --web.xml 【環境】 Windows XP Pro Eclipse3.3.2 apache2.2 tomcat6.0 jdk1.6.0_18 mysql-connector-java-5.1.12-bin.jar Struts2 以下に、context.xml、web.xml及び、サーブレットのコードを記載します ■web.xml=========== <?xml version="1.0" encoding="UTF-8"?> ~~(抜粋)~~ <resource-ref> <res-ref-name>test</res-ref-name> <res-type>javax.sql.DataSource</res-type> <res-auth>Container</res-auth> </resource-ref> </web-app> ■context.xml======= <?xml version="1.0" encoding="UTF-8"?> <Context displayName="test" docBase="test" path="/test" reloadable="false"> <Resource name="jdbc/test" auth="Container" type="javax.sql.DataSource" username="root" password="root" driverClassName="org.gjt.mm.mysql.Driver" url="jdbc:mysql://localhost/test?useUnicode=true&amp;characterEncoding=UTF-8" maxActive="4" maxWait="5000" maxIdle="2" validationQuery="select cont(*) from db_fuzoku" /> </Context> ■サーブレットコード(抜粋)===== public class test_Dao { DataSource ds; public ArrayList select(){ ArrayList list = new ArrayList(); try { // 初期コンテキストを取得 Context initCtx = new InitialContext(); Context envCtx = (Context) initCtx.lookup("java:comp/env"); // ルックアップしてデータソースを取得 ds = (DataSource) envCtx.lookup("jdbc/test"); } catch (Exception e) { e.printStackTrace(); } Connection con = null; Statement stmt = null; try { // データソースからConnectionを取得 con = ds.getConnection(); ==================== 以上、よろしくお願いします。

  • Tomcatを再起動するとエラーが解消する

    PostgreSQLを利用したJavaのシステムで、DB更新中に、エラーが発生することがあります。 その後、再処理を行うと、次のメッセージが出ます。 org.apache.commons.dbcp.SQLNestedException: Cannot get a connection, pool exhausted Tomcatを再起動すると、正常にDB更新が出来るようになります。 ほぼ毎日使っているシステムですが、1月18日と、4月26日の2回発生しています。 どのようなところを調査すればよいか、教えてください。 よろしくお願いします。

    • ベストアンサー
    • Java
  • Tomcat5.0でJNDI

    お世話になります。 Tomcat5.0で、JNDIを使ってコネクションプーリングを実現しようとしてますが、なかなかうまいこといきません。 コンテキストファイル(hoge.xml)の設定 前略 <Resource name="jdbc/hoge" auth="Container" type="javax.sql.DataSource"/> <ResourceParams name="jdbc/hoge">   <parameter>     <name>factory</name> <value>org.apache.commons.dbcp.BasicDataSourceFactory</value>   </parameter>   <parameter>     <name>driverClassName</name>     <value>com.mysql.jdbc.Driver</value>   </parameter>   <parameter>     <name>url</name>     <value>jdbc:mysql://localhost/hoge</value>   </parameter>   <parameter>     <name>username</name>     <value>hogeuser</value>   </parameter>   <parameter>     <name>password</name>     <value>hogepass</value>   </parameter> 中略 </ResourceParams> 後略 これを、トムキャットホーム\conf\Catalina\localhostに置いています。 Javaの方のソース String dsString = getServlet().getInitParameter("java:comp/env/jdbc/hoge"); InitialContext context = new InitialContext(); DataSource ds = (DataSource) context.lookup(dsString); Connection connection = ds.getConnection(); 実行すると、 名前 java:/comp/env/jdbc/hoge はこのコンテキストにバインドされていません という具合に怒られます。名前はjdbc/hogeで合ってると思うのですが、他に何かおかしいところがあるでしょうか。 また他に調べるべき点はどのようなところでしょうか。 どうぞよろしくご教授ください。

専門家に質問してみよう