S_a_k_Uの日記みたいなDB

~サクゥーと呼ばないで~

close=返却、そしてコネクションの確認と破棄と再取得

DBコネクションのプーリングを改めてお勉強。
@IT:現場に活かすJakarta Project 第6回
んで、CommonsのDBCPのソースを眺めてみたり。
org.apache.commons.dbcp.PoolableConnectionクラスがコネクションのラッパクラスで、closeメソッドみたら返却ってなコードになってる。
で、いわゆるDBのコネクションのcloseとは違うみたいね。


org.apache.commons.dbcp.GenericObjectPool#borrowObjectが、プーリングからコネクションを貸し出すロジックの肝か。
Ping Queryってのは、org.apache.commons.dbcp.BasicDataSourceのvalidationQueryの値を指定すればいいのね。
validationQueryを指定していないと、activeかどうかテストしないよと。
DBCPでは、org.apache.commons.dbcp.PoolableConnectionFactory#validateConnectionでPing QueryのSQL投げて、borrowObjectで例外拾って、コネクションを破棄して、も一回プールからコネクションを取得しますよと。

// GenericObjectPool#borrowObjectの抜粋

// activate & validate the object
try {
    // 取得したオブジェクトアクティブにする
    _factory.activateObject(pair.value);
    // validationQueryのSQLで確認
    // (_testOnBorrowはvalidationQueryが設定されてたらtrue)
    if(_testOnBorrow && !_factory.validateObject(pair.value)) { 
        throw new Exception("ValidateObject failed");
    }
    return pair.value;
}
catch (Throwable e) {
  // SQLで確認して例外をキャッチしたら
    // object cannot be activated or is invalid
    try {
        // コネクションを破棄して
        _factory.destroyObject(pair.value);
    } catch (Throwable e2) {
        // cannot destroy broken object
    }
    synchronized (this) {
        _numActive--;
        notifyAll();
    }
    if(newlyCreated) {
        throw new NoSuchElementException("Could not create a validated object, cause: " + e.getMessage());
    }
    else {
        // 再度プールからコネクションを取得する
        continue; // keep looping
    }
}

validationQueryを指定しとけば、DBMSでコネクションのタイムアウトが設定されたり、Webアプリと同期しないでサービスが再起動されるような場合でも、プーリングできます(コネクションを破棄して再取得します)よと。


Cosminexusの中のリソース参照のコネクションプーリングは、ちゃんとPing Queryでコネクションの生死を確認して、コネクションがDBMS側から切断されてる場合に、コネクションを破棄して再取得して、貸し出してると見える。