隨著 B/S 架構取代 C/S 成為企業級應用主流,Web 應用面臨高併發數據庫訪問挑戰。傳統「請求-建立連接-操作-關閉連接」模式在高併發下導致頻繁建立/銷毀連接開銷巨大、資源無序分配、甚至服務器崩潰。**數據庫連接池**技術通過「緩沖池」思想預建連接、復用連接、統一管理,成為解決此類瓶頸的標準方案。本文系統講解 JDBC 連接池核心原理、關鍵問題(併發、多庫、事務、分配釋放、配置維護)與生產級實現模型。
Class.forName("com.mysql.jdbc.Driver")DriverManager.getConnection(url, user, pwd)Statement/PreparedStatementconn.close()close(),連接泄漏最終拖垮數據庫基本思想:預先建立一定數量連接放入「緩沖池」,需要時取出,用完歸還。通過 minConn/maxConn 控制池規模,管理機制監控使用情況。
public synchronized Connection getConnection(long timeout) {
// 檢查空閒池、建立新連接、等待邏輯均在同步塊內
// 或使用 ReentrantLock + Condition 實現更精細控制
}
Java 內建同步支援使併發控制相對簡單,但高併發下鎖競爭可成為新瓶頸,生產級常用 ConcurrentLinkedQueue + Semaphore 無鎖/輕量鎖方案。
// 資源文件 db.properties
tx.url=jdbc:oracle:thin:@172.21.15.123:1521:tx_it
tx.user=yang
tx.password=yang321
report.url=jdbc:mysql://172.21.15.124:3306/report
report.user=readonly
report.password=readonly123
// 管理類單例模式,啟動時讀取配置建立多個連接池實例
// 每個池對應一組 url/user/password,以名稱管理
同一 URL 不同用戶憑證同樣支援:配置多條同 URL 不同 user/password 記錄。
conn.setAutoCommit(false) + commit()/rollback()分配邏輯:
conn.isValid() 或執行 SELECT 1)timeout,超時返回 null釋放邏輯:用完歸還空閒池,計數器遞減。
有效性檢測策略**:
| 策略 | 優點 | 缺點 |
|---|---|---|
| 專用檢測線程定時掃描 | 響應快,分配時無檢測開銷 | 消耗額外線程資源 |
| 分配前檢測 | 無額外線程,實時準確 | 增加分配延遲 |
| 驗證查詢 | 通用,跨數據庫 | 網絡往返開銷 |
職責**:單一數據庫的連接緩沖池
public class DBConnectionPool implements TimerListener {
private int checkedOut; // 已分配連接數
private ArrayList freeConnections; // 空閒池(按建立時間順序)
private int minConn, maxConn;
private String name, url, user, password;
private Timer timer; // 定時器(維持最小連接、檢測有效性)
public DBConnectionPool(String name, String url, String user, String pwd, int maxConn) { ... }
public synchronized Connection getConnection(long timeout) { ... } // 核心獲取邏輯
public synchronized void freeConnection(Connection con) { ... } // 歸還邏輯
public synchronized void release() { ... } // 關閉所有連接
private Connection newConnection() { ... } // 建立新連接
public synchronized void TimerEvent() { ... } // 定時任務:補充最小連接、清理無效連接
}
職責**:多連接池統一管理、驅動載入、配置解析
public class DBConnectionManager {
static private DBConnectionManager instance; // 單例
static private int clients;
private ArrayList drivers; // 載入的驅動
private HashMap pools; // name -> DBConnectionPool
static synchronized public DBConnectionManager getInstance() { ... }
private DBConnectionManager() { init(); }
private void init() { loadDrivers(props); createPools(props); }
private void loadDrivers(Properties props) { ... }
private void createPools(Properties props) { ... }
public Connection getConnection(String name) { ... }
public Connection getConnection(String name, long time) { ... }
public void freeConnection(String name, Connection con) { ... }
public synchronized void release() { ... }
}
public class MyServlet extends HttpServlet {
private DBConnectionManager connMgr;
public void init() throws ServletException {
connMgr = DBConnectionManager.getInstance(); // 啟動時初始化池
}
public void service(HttpServletRequest req, HttpServletResponse resp) {
Connection conn = connMgr.getConnection("tx"); // 獲取連接
try {
// 業務操作
} finally {
connMgr.freeConnection("tx", conn); // 必須歸還
}
}
public void destroy() {
connMgr.release(); // 關閉所有池
super.destroy();
}
}
本文給出的模型是教學級基礎實現。生產環境建議直接使用成熟開源連接池:
| 連接池 | 特點 | 適用場景 |
|---|---|---|
| HikariCP | 極致效能、輕量、零依賴、預設配置優秀 | **首選**,Spring Boot 2+ 預設 |
| Druid | 阿里出品、監控強、SQL 防注入、日誌分析 | 需強監控、安全審計的國內項目 |
| Tomcat JDBC Pool | Tomcat 內建、JMX 監控、公平鎖 | Tomcat 容器環境 |
| DBCP2 | Apache 老牌、功能全 | 歷史項目維護 |