概述
我们为什么需要连接池?
在JDBC
编程中,每次创建和断开Connection
对象都会消耗一定的时间和IO
资源。这是因为在Java
程序与数据库之间建立连接时,数据库端要验证用户名和密码。
并且要为这个连接分配资源,Java
程序则要把代表连接的java.sql.Connection
对象等加载到内存中,所以建立数据库连接的开销很大。
尤其是在大量的并发访问时,假如某网站一天的访问量是10
万,那么,该网站的服务器就需要创建、断开连接10
万次,频繁地创建、断开数据库连接势必会影响数据库的访问效率,甚至导致数据库崩溃。
我们为什么使用Druid?
Druid
是现阶段Java
中最好的数据库连接池,能够提供强大的监控和扩展功能。
Druid与各类连接池的性能对比(来源官方文档)
测试执行申请归还连接1,000,000
(一百万)次总耗时性能对比。Java 7
基准测试结果如下:
JDBC连接池类型 | 1个线程 | 2个线程 | 5个线程 | 10个线程 | 20个线程 | 50个线程 |
---|---|---|---|---|---|---|
Druid | 898 | 1,191 | 1,324 | 1,362 | 1,325 | 1,459 |
tomcat-jdbc | 1,269 | 1,378 | 2,029 | 2,103 | 1,879 | 2,025 |
DBCP | 2,324 | 5,055 | 5,446 | 5,471 | 5,524 | 5,415 |
BoneCP | 3,738 | 3,150 | 3,194 | 5,681 | 11,018 | 23,125 |
jboss-datasource | 4,377 | 2,988 | 3,680 | 3,980 | 32,708 | 37,742 |
C3P0 | 10,841 | 13,637 | 10,682 | 11,055 | 14,497 | 20,351 |
Proxool | 16,337 | 16,187 | 18,310(发生异常) | 25,945 | 33,706(发生异常) | 39,501(发生异常) |
结论
Druid
是性能最好的数据库连接池,tomcat-jdbc
和druid
性能接近。
proxool
在激烈并发时会抛异常,完全不靠谱。
c3p0
和proxool
都相当慢,慢到影响sql
执行效率的地步。
bonecp
性能并不优越,采用LinkedTransferQueue
并没有能够获得性能提升。
jboss-datasource
虽然稳定,但是性能很糟糕
该测试基于JDK7
,暂无JDK8
以上版本测试数据
Druid与各类连接池的功能对比(来源官方文档)
Druid | BoneCP | DBCP | C3P0 | Proxool | JBoss | Tomcat-Jdbc | |
---|---|---|---|---|---|---|---|
LRU | 是 | 否 | 是 | 否 | 是 | 是 | ? |
PSCache | 是 | 是 | 是 | 是 | 否 | 否 | 是 |
PSCache-Oracle-Optimized | 是 | 否 | 否 | 否 | 否 | 否 | 否 |
ExceptionSorter | 是 | 否 | 否 | 否 | 否 | 是 | 否 |
更新维护 | 是 | 否 | 否 | 否 | 否 | ? | 是 |
PSCache
PSCache
是数据库连接池的关键指标。在Oracle
中,类似SELECT NAME FROM USER WHERE ID = ?
这样的SQL
,启用PSCache
和不启用PSCache
的性能可能是相差一个数量级的。
Proxool
是不支持PSCache
的数据库连接池,如果你使用Oracle
、SQL Server
、DB2
、Sybase
这样支持游标的数据库,那你就完全不用考虑Proxool
。
PSCache-Oracle-Optimized
Oracle 10
系列的Driver
,如果开启PSCache
,会占用大量的内存,必须做特别的处理,启用内部的EnterImplicitCache
等方法优化才能够减少内存的占用。这个功能只有DruidDataSource
有。如果你使用的是Oracle Jdbc
,你应该毫不犹豫采用DruidDataSource
。
ExceptionSorter
ExceptionSorter
是一个很重要的容错特性,如果一个连接产生了一个不可恢复的错误,必须立刻从连接池中去掉,否则会连续产生大量错误。这个特性,目前只有JBossDataSource
和Druid
实现。Druid
的实现参考自JBossDataSource
,经过长期生产反馈补充。
源码分析版本
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.9</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.9</version>
</dependency>
Druid源码分析
Druid初始化
Druid如何获取连接
Druid如何销毁连接
Druid如何解析SQL
Druid Spring Boot配置项
配置application.yml
文件,前缀为spring.datasource.druid
,
该配置项是基于Druid 1.2.9
版本,,具体配置项如下:
推荐配置项
配置项 | 数据类型 | 默认值 | 说明 |
---|---|---|---|
url | String | null | 数据库连接地址 |
username | String | null | 数据库的连接用户名 |
password | String | null | 数据库的连接密码 |
initial-size | int | 0 | 初始化时直接创建连接的数量,可预热连接池,使得程序能快速获取连接 |
max-active | int | 8 | 最大连接池数量 |
min-idle | int | 0 | 最小连接池数量 |
max-wait | int | -1 | 获取连接时最大等待时间,单位毫秒。 |
validation-query | String | null | 用来检测连接是否有效的SQL ,要求是一个查询语句,如果validationQuery 为null ,testOnBorrow 、testOnReturn 、testWhileIdle 都不会起作用。Myql 推荐设置:SELECT 1 Oracle 推荐设置:SELECT 1 FROM dual |
扩展配置项
注意:版本非1.2.9
以上版本,推荐配置testOnReturn
、testOnBorrow
、testWhileIdle
这三个参数为以下默认值。
配置项 | 数据类型 | 默认值 | 说明 |
---|---|---|---|
test-on-return | boolean | false | 归还连接时执行validationQuery 检测连接是否有效,比较影响性能,推荐关闭false |
test-on-borrow | boolean | false | 获取连接时执行validationQuery 检测连接是否有效,非常影响性能,推荐关闭false |
test-while-idle | boolean | true | 申请连接的时候判断空闲时间如果大于timeBetweenEvictionRunsMillis ,则执行 validationQuery 检测连接是否有效。防止因为空闲时间太长, TCP 因各种原因断开连接。推荐开启 true |
validation-query-timeout | int | -1 | 设置执行validationQuery 的超时时间 |
时间关系,先挖坑,后续补充。