2011-10-03

Tags: connection-pool , 程式語言

這陣子因工作需要,必需寫一些對mySQL database頻繁存取的程式。理所當然的就一定會選用Connection Pool來加速DB連線的取得與管理。當時選用了DBCP與BoneCP兩種,下面是針對DBCP設置的SampleCode與心得筆記。


public class ConnectionManager {
private static final BasicDataSource dataSource;

static{
try {
Class.forName("com.mysql.jdbc.Driver");
dataSource = new BasicDataSource();
dataSource.setUrl("dbConnectURL");
dataSource.setUsername("dbUserName");
dataSource.setPassword("dbPassword");
dataSource.setMaxActive(dbPoolMaxActive); //connection pool的最大連線數
dataSource.setMaxIdle(dbPoolMaxIdle); //connection pool的最小連線數
dataSource.setMaxWait(10000); //單位為millisec。dataSource.getConnection()被呼叫時,超過多久時間未回應就回傳Exception訊息
dataSource.setValidationQuery("SELECT 1"); //用來驗証連線是否還活著。MySQL用的語法是用"SELECT 1",其它DB要設其它對應的語法
dataSource.setTestOnBorrow(true); //取回連線時是否要驗証連線還活著
dataSource.setTestWhileIdle(true); //idle的連線是否要驗証還活著
dataSource.setTimeBetweenEvictionRunsMillis(10000); //You have to set this value, otherwise even though
//you've asked connections to be tested while idle,
//the idle evicter thread will never run
dataSource.setMinEvictableIdleTimeMillis(60000); //Don't allow connections to hang out idle too long,
//never longer than what wait_timeout is set to on the
//mysql server.A few minutes or even fraction of a minute
//is sometimes okay here, it depends on your application
//and how much spikey load it will see
}
catch (Exception e) {
throw new RuntimeException(e);
}
}

public static synchronized Connection getConnection(){
try {
return dataSource.getConnection();
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
}

心得筆記
  1. 在mySQL裡執行"show variables"查詢,找出"wait_timeout參數"的設置時間(單位為秒)。Connection Pool的參數配置要配合此參數進行合適的調整,否則有時會出現遇想不到的問題。

    之前遇到DB的參數值為"wait_timeout=600"時,Connection Pool常出現Communications link failure的問題。這問題的根源其實在於DB,DB端timeout時間很短,所以Connection Pool的參數裡,每個連線的存活時間要跟著調小,以免發生DB端已把連線斷掉,Connection Pool卻不知道,進而導致程式取到已被斷開的連線,然後程式發生連線異常的問題。 
  2. DBCP的JavaDoc API在此,可查相關的設定明細說明。
  3. SampleCode裡的dataSource.setValidationQuery(...)dataSource.setMinEvictableIdleTimeMillis(...)跟每種不同DB特性的關聯較大,要視使用何種DB做對應調整。
  4. DataSource本身並不是ThreadSafe,如果程式會開啟多個Thread同時取用連線,要加synchronized語法(如SampleCode所示)。