數據庫連接是昂貴資源,優化核心在於復用連接、減少網絡交互、保證數據一致性。
每次請求創建連接:DriverManager.getConnection() 涉及網絡握手、認證、資源分配,極其耗時。
// 初始化池 (啟動時一次)
DataSource ds = new ComboPooledDataSource(); // 或 BasicDataSource
ds.setJdbcUrl("jdbc:mysql://localhost:3306/db");
ds.setUser("root");
ds.setPassword("pass");
ds.setMinPoolSize(5);
ds.setMaxPoolSize(20);
// 業務代碼中獲取/歸還
Connection conn = null;
try {
conn = ds.getConnection(); // 從池獲取,極快
// 業務邏輯
} finally {
if (conn != null) conn.close(); // 歸還池中,非真正關閉
}
| 參數 | 建議值 | 說明 |
|---|---|---|
| minPoolSize | 5-10 | 啟動預熱,避免冷啟動延遲 |
| maxPoolSize | 20-50 | 根據 CPU 核數與並發調整 |
| maxWait | 3000-5000ms | 獲取連接超時,防止無限等待 |
| idleConnectionTestPeriod | 300s | 定期檢測閒置連接有效性 |
| preferredTestQuery | SELECT 1 | 輕量級驗證查詢 |
| maxStatements | 100-500 | PreparedStatement 緩存大小 |
addBatch() + executeBatch() 減少網絡往返setInt()、setString() 自動轉義
// 1. 獲取預編譯語句
PreparedStatement ps = conn.prepareStatement(
"SELECT * FROM users WHERE username = ? AND status = ?"
);
// 2. 綁定參數 (索引從 1 開始)
ps.setString(1, "zhangsan");
ps.setInt(2, 1);
// 3. 執行查詢
ResultSet rs = ps.executeQuery();
while (rs.next()) {
// 處理結果
}
// 4. 關閉語句 (釋放游標、緩存)
ps.close(); // 重要!防止游標洩漏
// 批量插入示例
conn.setAutoCommit(false);
PreparedStatement batchPs = conn.prepareStatement(
"INSERT INTO logs (level, message, created_at) VALUES (?, ?, ?)"
);
for (LogEntry log : logs) {
batchPs.setString(1, log.getLevel());
batchPs.setString(2, log.getMessage());
batchPs.setTimestamp(3, new Timestamp(log.getTime()));
batchPs.addBatch();
}
int[] results = batchPs.executeBatch(); // 一次網絡往返
conn.commit();
batchPs.close();
| 隔離級別 | 臟讀 | 不可重複讀 | 幻讀 | 適用場景 |
|---|---|---|---|---|
| READ_COMMITTED (默認) | 防止 | 允許 | 允許 | 大多數業務,性能較好 |
| REPEATABLE_READ | 防止 | 防止 | 允許 | 需要一致性讀取的報表查詢 |
| SERIALIZABLE | 防止 | 防止 | 防止 | 極高一致性要求,性能最差 |
Connection conn = null;
try {
conn = ds.getConnection();
conn.setAutoCommit(false); // 關閉自動提交
conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
// 業務操作 1
updateAccountBalance(conn, fromAccount, -amount);
// 業務操作 2
updateAccountBalance(conn, toAccount, +amount);
// 記錄流水
insertTransactionLog(conn, fromAccount, toAccount, amount);
conn.commit(); // 提交事務
} catch (Exception e) {
if (conn != null) {
try { conn.rollback(); } catch (SQLException se) { log.error(se); }
}
throw new BusinessException("轉賬失敗", e);
} finally {
if (conn != null) {
try {
conn.setAutoCommit(true); // 還原自動提交 (歸還池前)
conn.close(); // 歸還連接池
} catch (SQLException e) { log.error(e); }
}
}
DriverManagerDataSourcevalidationQuery="SELECT 1" + testOnBorrow=trueSpring JdbcTemplate/NamedParameterJdbcTemplate、MyBatis、Hibernate 內部均封裝上述最佳實踐:
JDBC 優化本質是資源復用與網絡交互最小化。掌握連接池配置、PreparedStatement 正確用法、事務邊界控制三大核心,即可解決 95% 的數據庫性能問題。現代框架雖屏蔽細節,但理解底層原理對排查疑難雜症、調優關鍵路徑至關重要。