【数据库编程】7.连接池
1. 直接获取Connection问题
- 传统的JDBC数据库连接使用DriverManager来获取,每次向数据库建立连接的时候都要将Connection加载到内存中,在验证IP地址,用户名和密码(0.05s~1s时间)。需要数据库连接的时候,就向数据库请求一个,频繁地进行数据库连接操作将占用很多的系统资源,容易造成服务器崩溃。
- 每一次数据库连接,使用完成后都得断开,如果程序出现异常而未能关闭,将导致数据库内存泄漏,最终将导致重启数据库。
- 传统获取连接的方式,不能控制创建的连接数量,如果连接过多,也可能导致内存泄漏,MySQL奔溃。
2. 数据库连接池种类
- JDBC的数据库连接池使用javax.sql.DataSource,DataSource是一个接口,该接口通常由第三方提供实现。
- C3P0数据库连接池,速度相对较慢,稳定性高。(Hibernate, Spring)
- DBCP数据库连接池,速度相对C3P0较快,但不稳定。
- Proxool数据库连接池,有监控连接池状态的功能,稳定性较C3P0差一些。
- BoneCP数据库连接池,速度快。
- Druid(德鲁伊)是由阿里提供的数据库连接池,集DBCP、C3P0、Proxool优点于一身的数据库连接池。
3. 使用案例
下面案例都会测试连接500000次,统计耗费时间。
3.1 C3P0案例
3.1.1 手动配置参数
使用这种方式,需要在代码中手动配置数据库连接池相关参数,代码量较大。代码如下:
@Test
public void testC3P0_1() throws Exception {
// 获取值
Properties properties = new Properties();
properties.load(new FileInputStream("src\\mysql.properties"));
String user = properties.getProperty("user");
String password = properties.getProperty("password");
String dirver = properties.getProperty("dirver");
String url = properties.getProperty("url");
// 设置相关参数
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setUser(user);
dataSource.setPassword(password);
dataSource.setDriverClass(dirver);
dataSource.setJdbcUrl(url);
// 初始化连接数
dataSource.setInitialPoolSize(10);
// 最大连接数
dataSource.setMaxPoolSize(50);
long start = System.currentTimeMillis();
for (int i = 0; i < 500000; i++) {
Connection connection = dataSource.getConnection();
connection.close();
}
long end = System.currentTimeMillis();
System.out.println("C3P0 500000次连接耗时:" + (end - start) / 1000.0 + "s");
}
本机耗时3.359s。运行结果如下:
3.1.2 使用配置文件
在src目录下创建一个文件c3p0-config.xml,文件内容如下:
<c3p0-config>
<named-config name="c3p0_dataSource">
<!-- 驱动类 -->
<property name="driverClass">com.mysql.jdbc.Driver</property>
<!-- URL -->
<property name="jdbcUrl">jdbc:mysql://localhost:3306/db02?rewriteBatchedStatements=true</property>
<!-- 用户名 -->
<property name="user">root</property>
<!-- 密码 -->
<property name="password">123456</property>
<!-- 每次增长的连接数 -->
<property name="acquireIncrement">5</property>
<!-- 初始的连接数 -->
<property name="initialPoolSize">10</property>
<!-- 最小连接数 -->
<property name="minPoolSize">5</property>
<!-- 最大连接数 -->
<property name="maxPoolSize">50</property>
<!-- 可连接的最多的命令对象数 -->
<property name="maxStatements">5</property>
<!-- 每个连接对象可连接的最多的命令对象数 -->
<property name="maxStatementsPerConnection">2</property>
</named-config>
</c3p0-config>
此时代码量相较手动配置就会少很多,代码如下:
@Test
public void testC3P0_2() throws SQLException {
ComboPooledDataSource dataSource = new ComboPooledDataSource("c3p0_dataSource");
long start = System.currentTimeMillis();
for (int i = 0; i < 500000; i++) {
Connection connection = dataSource.getConnection();
connection.close();
}
long end = System.currentTimeMillis();
System.out.println("C3P0 500000次连接耗时:" + (end - start) / 1000.0 + "s");
}
本机耗时3.032s,两次结果接近。运行结果如下:
3.2 Druid案例
首先需要编写一个druid.properties(文件名随意)配置文件,内容如下:
diverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/db02?rewriteBatchedStatements=true
username=root
password=123456
# 初始连接数
initialSize=10
# 最小空闲连接数
minIdle=5
# 最大连接数
maxActive=20
# 最大等待时间,即超时时间,单位:毫秒
maxWait=5000
之后编写Java代码,测试连接500000耗费的时间,代码如下:
@Test
public void testDruid() throws Exception {
// 读取配置
Properties properties = new Properties();
properties.load(new FileInputStream("src\\druid.properties"));
DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
long start = System.currentTimeMillis();
for (int i = 0; i < 500000; i++) {
Connection connection = dataSource.getConnection();
connection.close();
}
long end = System.currentTimeMillis();
System.out.println("C3P0 500000次连接耗时:" + (end - start) / 1000.0 + "s");
}
本机耗时0.814s,Druid速度相较C3P0速度有非常大的提升。运行结果如下:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)