数据库连接池的工作机制
数据库连接池的工作机制
什么是数据库连接池?
数据库连接池是池化技术在数据库访问场景下的典型应用。它本质上是一个存放数据库连接的缓冲区(也就是一个“池子”),负责预先创建一批数据库连接,然后让多个请求循环复用这些连接。
核心工作流程
初始化阶段: 应用程序启动时,连接池会根据配置预先创建一定数量的数据库连接(即初始连接数或最小连接数),并将其放入内部连接队列中,以便快速响应初期请求 。
获取连接: 当业务线程需要访问数据库时,向连接池申请连接。若池中有空闲连接,则直接分配;若无空闲连接但当前连接总数未达上限,则创建新连接;若已达最大连接数,请求线程将进入等待队列,直到有连接归还或超时 。
归还连接: 业务使用完连接后,调用关闭方法(如 close()),此时连接并非物理断开,而是被标记为空闲并返回连接池,等待下一次复用 。
销毁连接: 连接池会定期扫描,若连接空闲时间超过最大空闲时间,或连接总存活时间达到最大生命周期,连接池将主动关闭并移除该连接,以释放资源并防止连接老化
为什么要用连接池?--如果没有池
每次执行SQL前都新建一个数据库连接,用完立即关闭,这个过程非常昂贵,主要包括:
-
TCP三次握手:与数据库服务器建立网络连接。
-
数据库认证:进行用户名、密码验证。
-
分配资源:数据库为每个连接分配内存、CPU上下文等。
-
断开清理:连接关闭时还要四次挥手、释放资源。
在高并发场景下,每秒钟有上千个请求,每个请求都重复这整套流程,会导致:
-
数据库CPU飙升(频繁处理握手/挥手)。
-
响应时间极大增加(大部分时间花在连接建立上)。
-
数据库连接数被打满,后续请求直接失败。
影响因素
1. 最小连接数
是连接池一直保持的数据库连接,所以如果应用程序对数据库连接的使用量不大,将会有大量的数据库连接资源被浪费。
2. 最大连接数
是连接池能申请的最大连接数,如果数据库连接请求超过此数,后面的数据库连接请求将被加入到等待队列中,这会影响之后的数据库操作。
3. 最小连接数与最大连接数差距
最小连接数与最大连接数相差太大,那么最先的连接请求将会获利,之后超过最小连接数量的连接请求等价于建立一个新的数据库连接。不过,这些大于最小连接数的数据库连接在使用完不会马上被释放,它将被放到连接池中等待重复使用或是空闲超时后被释放。
常见数据库连接池--Java生态
HikariCP--以速度快为优势
Spring Boot 2.x 及以上版本的默认连接池,社区活跃,更新稳定。以简洁、高性能和专注核心功能著称。
使用:
1、添加依赖:
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>5.1.0</version>
</dependency>
2、代码配置与使用
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
// 1. 配置连接池
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:mysql://localhost:3306/mydb");
config.setUsername("user");
config.setPassword("password");
config.setMaximumPoolSize(20);
config.setMinimumIdle(5);
// 2. 创建数据源
HikariDataSource dataSource = new HikariDataSource(config);
// 3. 获取并使用连接 (try-with-resources会自动关闭)
try (Connection conn = dataSource.getConnection();
PreparedStatement stmt = conn.prepareStatement("SELECT * FROM users")) {
// 执行你的数据库操作
} catch (SQLException e) {
e.printStackTrace();
}
Druid--以监控功能强大著称
Druid不仅是一个数据库连接池,还包含一个ProxyDriver、一系列内置的JDBC组件库、一个SQL Parser。
使用:
1、添加依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.23</version>
</dependency>
2、代码配置和使用
import com.alibaba.druid.pool.DruidDataSourceFactory;
// 1. 加载配置 (通常在 druid.properties 文件)
Properties props = new Properties();
props.load(new FileInputStream("druid.properties"));
// 2. 创建数据源
DataSource dataSource = DruidDataSourceFactory.createDataSource(props);
// 3. 获取并使用连接 (和HikariCP完全一样)
try (Connection conn = dataSource.getConnection();
PreparedStatement stmt = conn.prepareStatement("SELECT * FROM users")) {
// 执行你的数据库操作
} catch (SQLException e) {
e.printStackTrace();
}
配置文件:
driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/mydb
username=user
password=password
initialSize=5
maxActive=20
maxWait=3000
浙公网安备 33010602011771号