- PR -

DBとのコネクションをstaticで持つことについて

投稿者投稿内容
cyanberry
常連さん
会議室デビュー日: 2005/01/07
投稿数: 37
投稿日時: 2005-01-07 18:14
複数のDB(mysql)に接続するサーブレット(tomcat)を構築しています。

現状は、DBとのコネクションをstaticで保持し使いまわしていますが、信頼性、安全性の観点から不安があります。

そこで、皆さんのご意見をお伺いしたいのですが、コネクションをstaticで保持することはどうなのでしょうか?メリット、デメリット等ありましたら、ご教授願います。
山本 裕介
ぬし
会議室デビュー日: 2003/05/22
投稿数: 2415
お住まい・勤務地: 恵比寿
投稿日時: 2005-01-07 18:15
>現状は、DBとのコネクションをstaticで保持し使いまわしていますが、信頼性、安全性の観点から不安があり
>ます。
まず、cyanberry さんはどのような不安がありますかね?
すでに問題だと感じているのであればやらなければいいわけですよね。
その問題を超えて何らかのメリットを感じているのであればそれを挙げて頂いた方が議論もしやすいと思います。

[ メッセージ編集済み 編集者: インギ 編集日時 2005-01-07 18:16 ]
cyanberry
常連さん
会議室デビュー日: 2005/01/07
投稿数: 37
投稿日時: 2005-01-07 18:21
早速の回答ありがとうございます。

不安な点は、

・複数のスレッドが1つのコネクションを使いまわすことに問題ないか
・コネクションをクローズしないことにより、リソースが食われて、tomcatの性能が落ちるのではないか
・コネクションが途中で切れたらどうなってしまうのか

という点です。
メリットとして感じているのは、

・ソースの簡略化
・DBアクセスする毎にコネクションを生成するよりも性能がよいのでは?(予想)

という点です。
よろしくお願いします。


[ メッセージ編集済み 編集者: cyanberry 編集日時 2005-01-07 18:24 ]
がるがる
ぬし
会議室デビュー日: 2002/04/12
投稿数: 873
投稿日時: 2005-01-07 18:42
どももです。がると申します。
この辺の「どーやってDBコネクションを持つか」っていう
お話は結構あちこちで出回ってますね。

で。「個人的1流儀」としての、私のやり方を簡単に。
なにか参考にでもなれば幸いです。

私は、こーゆー時は「クラス作って対応」してます。
大雑把にイメージが湧きそうな、コードもどきを。
コード:

static class util {
//public:
static DBハンドルの型 get_dbhandle(void) {
if (null == DBハンドル_) {
// DB接続処理
}
// 必要なら、ここで「接続が切れていないか」チェックする

// 必要なら、この辺のタイミングでthread競合対策をかける

//
return DBハンドル_;
}


//private:
static DBハンドルの型 DBハンドル_ = null;
}



これで、
引用:

・複数のスレッドが1つのコネクションを使いまわすことに問題ないか


もしDBハンドルの形式が「スレッド非対応」なら、クラス内で処理してあげればOKになる

引用:

・コネクションをクローズしないことにより、リソースが食われてtomcatの性能が落ちるのではないか


めったにないと思うのですが。
場合によっては「DBハンドルがn回借り出されるたびにclose+openを行う」
ロジックを追加してやれば、リソースの開放は多分可能です。
# でもまぁ、メモリリークするようなハンドルもそうはないと思いますが :-P

引用:

・コネクションが途中で切れたらどうなってしまうのか


丁寧に作るならクラス内で対応

って感じで片付くと思うです。

引用:

・ソースの簡略化
・DBアクセスする毎にコネクションを生成するよりも性能がよいのでは?(予想)


んっと。ソースの簡略化は「open処理が一箇所」って程度に便利
だと思うのですが。
DBのコネクションって結構リソースだの時間だの食うので、個人的には
性能的にとても美味しいと思うです。

参考にでもなれば幸いです。

(ソースのメソッド&変数にstaticを入れ忘れたので編集 ^^;)

[ メッセージ編集済み 編集者: がるがる 編集日時 2005-01-07 18:43 ]
YOU@IT
ぬし
会議室デビュー日: 2002/03/29
投稿数: 284
お住まい・勤務地: 大阪
投稿日時: 2005-01-07 21:43

基本的には、staticで持つことにはNoですね。

Connectionの使い道がわかりませんが、例えばトランザクショナルな更新処理をする
のであれば、別のスレッドがコミットorロールバックしてしまいますよね?

sataticなフィールドに保持したからソースを簡略化できるとは思いませんし、
コネクションを確立するコストについても、コネクションプーリングを
使えば無視できる程度だと思います。



vincent
大ベテラン
会議室デビュー日: 2004/07/09
投稿数: 142
投稿日時: 2005-01-07 22:43
リソースや同期の問題もありますが、DB接続のような共通サービスは
staticにするよりSingletonパターンを使ってインスタンスとして提供するほうが
望ましいと思います。
H2
ぬし
会議室デビュー日: 2001/09/06
投稿数: 586
お住まい・勤務地: 港
投稿日時: 2005-01-07 23:35
すでに指摘がありますが、static (Singletonでも)ですとマルチ・スレッド環境で同じConnectionを複数のスレッドで同時に使ってしまい、不思議な動作をするおそれがあります。

参考までに下のコードはjava.lang.ThreadLocalを使って同スレッドでは同じConnectionオブジェクトを使いつつ、別のスレッド間では共有しません。スレッドごとに新しいConnectionを作ってしまうのでgetConnection()内でコネクションプールを使うと良いかもしれません。

コード:
public class DBUtil {

    private static final ThreadLocal session = new ThreadLocal();

    public static Connection getConnection() throws Exception {

        Connection con = (Connection) session.get();

        // まだこのThreadに存在しなければ、新しくConnectionをオープンする
        if (con == null) {
            con = ...          //新しいコネクションを作る。(コネクションプールからでも可)
            session.set(con);   //ThreadLocalに登録しておく
        }
        return con;
    }

    public static void closeConnection() throws Exception {
        Connection con = (Connection) session.get();
        session.set(null);
        if (con != null)
            con.close(); //(コネクションプールの場合はcloseしないでプールに返却する)
    }
}


H2
ぬし
会議室デビュー日: 2001/09/06
投稿数: 586
お住まい・勤務地: 港
投稿日時: 2005-01-07 23:43
使い方を記述するのを忘れてました。DBUtil.getConnection();は何回でも呼べます。

コード:
   Connection con1 = DBUtil.getConnection();
   //con1を使ってデータベースとやりとり

   ... ほかの事をする  ... 

   //またConnectionを取り出す。
   Connection con2 = DBUtil.getConnection();  //同じスレッドなのでcon1==con2
   //con2を使ってデータベースとやりとり

   DBUtil.closeConnection(); //このスレッドのコネクションを閉じる con1とcon2は両方closeされる。


スキルアップ/キャリアアップ(JOB@IT)