Java中常用的数据库连接池_动力节点Java学院整理

定义

数据库连接是一种关键的有限的昂贵的资源,这一点在多用户的网页应用程序中体现得尤为突出。对数据库连接的管理能显著影响到整个应用程序的伸缩性和健壮性,影响到程序的性能指标。数据库连接池正是针对这个问题提出来的。

数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个;释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗漏。这项技术能明显提高对数据库操作的性能。

参考资料

DBCP

下载地址:http://commons.apache.org/proper/commons-dbcp/download_dbcp.cgi

相关属性说明: http://commons.apache.org/proper/commons-dbcp/configuration.html

c3p0

下载地址:http://sourceforge.net/projects/c3p0/

相关属性说明: http://www.mchange.com/projects/c3p0/

Druid

下载地址:http://repo1.maven.org/maven2/com/alibaba/druid/

相关属性说明: https://github.com/alibaba/druid/wiki

 Proxool

下载地址:http://proxool.sourceforge.net/

相关属性说明:https://github.com/proxool/proxool

2. 数据库连接池

2.1 原理

连接池基本的思想是在系统初始化的时候,将数据库连接作为对象存储在内存中,当用户需要访问数据库时,并非建立一个新的连接,而是从连接池中取出一个已建立的空闲连接对象。使用完毕后,用户也并非将连接关闭,而是将连接放回连接池中,以供下一个请求访问使用。而连接的建立、断开都由连接池自身来管理。同时,还可以通过设置连接池的参数来控制连接池中的初始连接数、连接的上下限数以及每个连接的最大使用次数、最大空闲时间等等,也可以通过其自身的管理机制来监视数据库连接的数量、使用情况等。

2.2 常见数据库连接池及其特点

在Java中开源的常用的数据库连接池有以下几种 :

1)DBCP

DBCP是一个依赖Jakarta commons-pool对象池机制的数据库连接池.DBCP可以直接的在应用程序中使用,Tomcat的数据源使用的就是DBCP。

2)c3p0

c3p0是一个开放源代码的JDBC连接池,它在lib目录中与Hibernate一起发布,包括了实现jdbc3和jdbc2扩展规范说明的Connection 和Statement 池的DataSources 对象。

3)Druid

阿里出品,淘宝和支付宝专用数据库连接池,但它不仅仅是一个数据库连接池,它还包含一个ProxyDriver,一系列内置的JDBC组件库,一个SQL Parser。支持所有JDBC兼容的数据库,包括Oracle、MySql、Derby、Postgresql、SQL Server、H2等等。
Druid针对Oracle和MySql做了特别优化,比如Oracle的PS Cache内存占用优化,MySql的ping检测优化。

Druid提供了MySql、Oracle、Postgresql、SQL-92的SQL的完整支持,这是一个手写的高性能SQL Parser,支持Visitor模式,使得分析SQL的抽象语法树很方便。

简单SQL语句用时10微秒以内,复杂SQL用时30微秒。

通过Druid提供的SQL Parser可以在JDBC层拦截SQL做相应处理,比如说分库分表、审计等。Druid防御SQL注入攻击的WallFilter就是通过Druid的SQL Parser分析语义实现的。

4) proxool

Proxool是一种Java数据库连接池技术。sourceforge下的一个开源项目,这个项目提供一个健壮、易用的连接池,最为关键的是这个连接池提供监控的功能,方便易用,便于发现连接泄漏的情况。目前是和DBCP以及C3P0一起,最为常见的三种JDBC连接池技术。目前,Hibernate官方宣布由于Bug太多不再支持DBCP,而推荐使用 Proxool或C3P0。

3. 主要配置说明

连接池配置大体可以分为基本配置、关键配置、性能配置等主要配置,缺少proxool相关配置。

3.1 基本配置

基本配置是指连接池进行数据库连接的四个基本必需配置:

传递给JDBC驱动的用于连接数据库的用户名、密码、URL以及驱动类名。

  DBCP c3p0 Druid
用户名 username user username
密码 password password password
URL url jdbcUrl jdbcUrl
驱动类名 driverClassName driverClass driverClassName

注:在Druid连接池的配置中,driverClassName可配可不配,如果不配置会根据url自动识别dbType(数据库类型),然后选择相应的driverClassName。

3.2 关键配置

为了发挥数据库连接池的作用,在初始化时将创建一定数量的数据库连接放到连接池中,这些数据库连接的数量是由最小数据库连接数来设定的。无论这些数据库连接是否被使用,连接池都将一直保证至少拥有这么多的连接数量。连接池的最大数据库连接数量限定了这个连接池能占有的最大连接数,当应用程序向连接池请求的连接数超过最大连接数量时,这些请求将被加入到等待队列中。

最小连接数:

是数据库一直保持的数据库连接数,所以如果应用程序对数据库连接的使用量不大,将有大量的数据库资源被浪费。

初始化连接数:

连接池启动时创建的初始化数据库连接数量。

最大连接数:

是连接池能申请的最大连接数,如果数据库连接请求超过此数,后面的数据库连接请求被加入到等待队列中。

最大等待时间:

当没有可用连接时,连接池等待连接被归还的最大时间,超过时间则抛出异常,可设置参数为0或者负数使得无限等待(根据不同连接池配置)。

  DBCP c3p0 Druid
最小连接数 minIdle(0) minPoolSize(3) minIdle(0)
初始化连接数 initialSize(0) initialPoolSize(3) initialSize(0)
最大连接数 maxTotal(8) maxPoolSize(15) maxActive(8)
最大等待时间 maxWaitMillis(毫秒) maxIdleTime(0秒) maxWait(毫秒)

注1:在DBCP连接池的配置中,还有一个maxIdle的属性,表示最大空闲连接数,超过的空闲连接将被释放,默认值为8。对应的该属性在Druid连接池已不再使用,配置了也没有效果,c3p0连接池则没有对应的属性。

注2:数据库连接池在初始化的时候会创建initialSize个连接,当有数据库操作时,会从池中取出一个连接。如果当前池中正在使用的连接数等于maxActive,则会等待一段时间,等待其他操作释放掉某一个连接,如果这个等待时间超过了maxWait,则会报错;如果当前正在使用的连接数没有达到maxActive,则判断当前是否空闲连接,如果有则直接使用空闲连接,如果没有则新建立一个连接。在连接使用完毕后,不是将其物理连接关闭,而是将其放入池中等待其他操作复用。

3.3 性能配置

预缓存设置:

即是PSCache,PSCache对支持游标的数据库性能提升巨大,比如说oracle。JDBC的标准参数,用以控制数据源内加载的PreparedStatements数量。但由于预缓存的statements属于单个connection而不是整个连接池,所以设置这个参数需要考虑到多方面的因素。

单个连接拥有的最大缓存数:要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。在Druid中,不会存在Oracle下PSCache占用内存过多的问题,可以把这个数值配置大一些,比如说100

  DBCP c3p0 Druid
开启缓存功能 poolPreparedStatements maxStatements poolPreparedStatements
单个连接拥有的最大缓存数 maxOpenPrepared- Statements maxStatementsPer- Connection maxOpenPrepared- Statements

连接有效性检测设置:

连接池内部有机制判断,如果当前的总的连接数少于miniIdle,则会建立新的空闲连接,以保证连接数得到miniIdle。如果当前连接池中某个连接在空闲了timeBetweenEvictionRunsMillis时间后任然没有使用,则被物理性的关闭掉。有些数据库连接的时候有超时限制(mysql连接在8小时后断开),或者由于网络中断等原因,连接池的连接会出现失效的情况,这时候设置一个testWhileIdle参数为true,可以保证连接池内部定时检测连接的可用性,不可用的连接会被抛弃或者重建,最大情况的保证从连接池中得到的Connection对象是可用的。当然,为了保证绝对的可用性,你也可以使用testOnBorrow为true(即在获取Connection对象时检测其可用性),不过这样会影响性能。

  DBCP c3p0 Druid
申请连接检测 testOnBorrow testConnectionOnCheckin testOnBorrow
是否超时检测 testWhileIdle   testWhileIdle
空闲时间 timeBetweenEvictionRunsMillis idleConnectionTestPeriod timeBetweenEvictionRunsMillis
校验用sql语句 validationQuery preferredTestQuery validationQuery
归还连接检测 testOnReturn testConnectionOnCheckout testOnReturn

超时连接关闭设置:

removeAbandoned参数,用来检测到当前使用的连接是否发生了连接泄露,所以在代码内部就假定如果一个连接建立连接的时间很长,则将其认定为泄露,继而强制将其关闭掉。

  DBCP c3p0 Druid
是否超时关闭连接 removeAbandoned breakAfterAcquireFailure removeAbandoned
超时时间 removeAbandonedTimeout checkoutTimeout removeAbandonedTimeout
是否记录日志 logAbandoned   logAbandoned

c3p0重连设置:

设置获取连接失败后,是否重新连接以及间隔时间。

  DBCP c3p0 Druid
重连次数   acquireRetryAttempts  
间隔时间   acquireRetryDelay  

4. 配置详解

4.1 DBCP 属性说明表

属性(Parameter) 默认值(Default) 描述(Description)
username   传递给JDBC驱动的用于建立连接的用户名(The connection username to be passed to our JDBC driver to establish a connection.)
password     传递给JDBC驱动的用于建立连接的密码(The connection password to be passed to our JDBC driver to establish a connection.)
url   传递给JDBC驱动的用于建立连接的URL(The connection URL to be passed to our JDBC driver to establish a connection.)
driverClassName   使用的JDBC驱动的完整有效的java 类名(The fully qualified Java class name of the JDBC driver to be used.)
defaultAutoCommit driver default 连接池创建的连接的默认的auto-commit状态,没有设置则不会自动提交(The default auto-commit state of connections created by this pool. If not set then the setAutoCommit method will not be called.)
initialSize 0 初始化连接:连接池启动时创建的初始化连接数量(The initial number of connections that are created when the pool is started.
maxTotal 8 最大活动连接:连接池在同一时间能够分配的最大活动连接的数量, 如果设置为非正数则表示不限制(The maximum number of active connections that can be allocated from this pool at the same time, or negative for no limit.)
maxIdle 8 最大空闲连接:连接池中容许保持空闲状态的最大连接数量,超过的空闲连接将被释放,如果设置为负数表示不限制(The maximum number of connections that can remain idle in the pool, without extra ones being released, or negative for no limit.)
minIdle 0 最小空闲连接:连接池中容许保持空闲状态的最小连接数量,负数表示没有现在(The maximum number of connections that can remain idle in the pool, without extra ones being released, or negative for no limit.)
注意:如果在某些负载比较大的系统中将maxIdel设置过小时,很可能会出现连接关闭的同时新连接马上打开的情况.这是由于关闭连接的线程比打开的快导致的.所以,对于这种系统中,maxIdle的设定值是不同的但是通常首选默认值
(NOTE: If maxIdle is set too low on heavily loaded systems it is possible you will see connections being closed and almost immediately new connections being opened. This is a result of the active threads momentarily closing connections faster than they are opening them, causing the number of idle connections to rise above maxIdle. The best value for maxIdle for heavily loaded system will vary but the default is a good starting point.)
maxWaitMillis indefinitely 最大等待时间:当没有可用连接时,连接池等待连接被归还的最大时间(以毫秒计数),超过时间则抛出异常,如果设置为-1表示无限等待(The maximum number of milliseconds that the pool will wait (when there are no available connections) for a connection to be returned before throwing an exception, or -1 to wait indefinitely.)
validationQuery     SQL查询,用来验证从连接池取出的连接,在将连接返回给调用者之前.如果指定,则查询必须是一个SQL SELECT并且必须返回至少一行记录(The SQL query that will be used to validate connections from this pool before returning them to the caller. If specified, this query MUST be an SQL SELECT statement that returns at least one row. If not specified, connections will be validation by calling the isValid() method.)
testOnCreate false