现在的位置: 首页 > 数据库 > 正文

数据库连接池dbcp整理

2019年08月15日 数据库 ⁄ 共 5908字 ⁄ 字号 评论关闭

1. 简介

DBCP(DataBase Connection Pool),数据库连接池。是 apache 上的一个 java 连接池项目,也是 tomcat 使用的连接池组件。单独使用dbcp需要3个包:common-dbcp.jar,common-pool.jar,common-collections.jar由于建立数据库连接是一个非常耗时耗资源的行为,所以通过连接池预先同数据库建立一些连接,放在内存中,应用程序需要建立数据库连接时直接到连接池中申请一个就行,用完后再放回去。

dbcp提供了数据库连接池可以在spring,iBatis,hibernate中调用dbcp完成数据库连接,框架一般都提供了dbcp连接的方法;

tomcat中也提供了dbcp的jndi设置方法,也可以不在框架中使用dbcp,单独使用dbcp需要3个包:common-dbcp.jar,common-pool.jar,common-collections.jar

2.连接池扼要

JDBC是一套通用的Java语言与多种数据库(文件)通讯的标准API。大部分针对数据库服务器(例如Oracle, MySQL等等)的JDBC实现都是基于TCP/IP连接的客户端-服务器端通讯方式。

当我们需要执行一个数据库操作时,有下面三步:

1. 客户端与服务器之间建立一个数据库连接 

2. 执行某种数据库操作 

3. 断开连接 

如果每次处理都要走上面的三步,则应用程序与数据库服务器都要将大量的时间和资源消耗在数据连接的断开与建立上。对于某些数据库系统,一个数据库连接就是一个进程,而且数据库连接通常要占用不少资源,如排序区/Join区等等。对于并发较大的系统,建立一次连接然后缓存起来连续使用,直到程序结束等情况下再释放连接,就能够将系统资源集中在对数据库操作的处理上,从而大大提高性能。通常情况下将数据连接的建立和断开委托给一种能够数据库连接池的组件或服务进行管理。而DBCP, C3p0, Proxool等都是常用的开源的连接池组件。

就好像A公司在郊外,他们公司附近没有出租车。如果A公司有人要出去办事,他必须打电话给出租公司订车,用完车后他还要付账报销。 这样每个人出去一趟都必须订车、退车和报销。员工的很多时间白白花费在这上面了。于是A公司跟出租车公司定了一个合同,出租车公司给了他们一个车队。要用车随时去楼下找车队就可以了,用完了也不必结帐,A公司统一跟出租车公司订车和结帐。这个车队就好比连接池,由公司(应用程序)来统一向出租车公司(数据库服务器)订车(建立连接)和退车(关闭连接)。

 

3.DBCP的配置参数以及背后的原理

Commons-dbcp连接池的配置参数比较多,也比较复杂,主要分为

· Jdbc连接参数(username, password, url, driverClassName, connectionProperties ) 

· 事务处理参数 (defaultAutoCommit, defaultReadOnly, defaultTransactionIsolation, defaultCatalog) 

· 连接池参数(详见下文) 

· 连接池中链接存活性测试参数(详见下文) 

· 预处理查询池化参数(poolPreparedStatements, maxOpenPreparedStatements) 

· 丢弃失效链接相关参数(详见下文)以及一个控制是否可以正常情况下处于访问连接池包装下的底层JDBC链接参数(accessToUnderlyingConnectionAllowed) 

其中Jdbc链接参数、事务处理都跟连接池关系不大,另预处理查询池化参数本文不详细叙述。有关commons-dbcp的详细参数配置信息请参考官方文档。 

 

4.连接池的配置

再用车队来比喻,出租车公司每提供一辆车给A公司,A公司肯定要付出一定费用。这时候维持车队的大小就很重要了,在项目少用车少的时候,车队肯定要减少,不然很多空闲车辆也要付出成本;在项目多用车多的时候,肯定要扩大车队,不然车不够用,车队忙不过来。A公司可以简单地设地两个阀值来动态调节车队中空闲的车辆数目以满足动态需求,一个是最小空闲车辆数(最小空空闲连接数(minIdle),当剩余的空车数目小于该数目时,A公司就向出租车公司请求加入新车。 一个是最大空闲车辆数(maxIdle),当剩余的车大于该数目时,就将刚刚用用完的车还给出租车公司从而减少车队数量。 

另外,这家出租车公司可能要为多个客户服务,要考虑能够提供给A公司的最大的车数量,不能超过某个数量(maxActive)。所以A公司想出租车申请新车时首先要看下当前正在用的车辆数目是否超过了这个最大数目,如果没有超过那就直接申请新车,否则可以让申请者(应用程序中执行请求的线程)等待 (maxWait<=0, 无限等待; maxWait>0 当等待时间超过 maxWait时,失败)。

在连接池中,这几个参数是十分重要的,官方的说明如下,是我们调节系统性能时需要认真考虑的值。

Parameter

Default

Description

initialSize

0

The initial number of connections that are created when the pool is started.

Since: 1.2
线程池启动时初始化的连接数 

maxActive

8

The maximum number of active connections that can be allocated from this pool at the same time, or non-positive 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 minimum number of connections that can remain idle in the pool, without extra ones being created, or zero to create none.
最小空闲连接数。 

maxWait

indefinitely

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.
(在没有连接可用时)连接池等待一个数据连接可用时的以毫秒计的最大等待时间,超时以后抛出异常, -1 则将无限等待 

实际上,Dbcp 依赖于 commons-pool 来存储连接对象。 BasicDataSource默认使用GenericObjectPool来管理连接对象。除了请求的线程会在请求和返回连接过程中影响池中连接实例外,另有一个跑着GenericObjectPool.Evictor类型 (implements Runnable) 的实例的线程,也会影响池中的数据库连接。

 

5.使用注意点

1) 如果maxIdle 设置太低,在高负载系统中,连接的打开时间比关闭的时间快,会引起连接池中的idle的个数上升超过maxIdle,造成频繁的销毁和创建,类似于jvm参数中的Xmx设置。

2) minIdle,该参数越接近maxIdle,性能越好,因为连接的创建和销毁,都是需要消耗资源的,但是不能太大,因为在机器很空闲的时候,也会创建低于minIdle个数的连接,类似于jvm参数中的Xms设置。

3) PreparedStatements会在数据库中保持打开的游标,这样会造成一个连接超出数据库游标限制, 特别是当maxOpenPreparedStatements 被设置成 default (unlimited),并且应用在一个连接上创建了大量不同PreparedStatements时,为了避免这个问题, maxOpenPreparedStatements 应该设置为一个小于数据库在一个连接上允许打开最大游标数。

4) poolPreparedStatements,经过测试,开启后的性能没有关闭的好,或者相差不大,没有本质的提高。

5) 对性能影响比较大的两个参数:

testOnBorrow:这个默认的之是true,对性能影响很大,因为每次从池中借出对象时进行一次验证,系统开销很大,实际测试中发现,性能差距有7-10倍的样子。

maxIdle:如果这个参数的值比maxActive低,在高负载的情况下就会产生很多time_waited线程。根据我们的测试结果,这个值最好和maxActive相同或者是设成-1。这样才能在高并发下,应用到数据库的连接也是稳定的使用固有的connection。否则dbcp会频繁创建新的连接,丢弃老的连接。而创建连接这个操作,比验证还要昂贵。

由于将maxIdle设置了一个比较高的值,应用就会在系统高峰时期创建的连接就会维持在那里。在空闲的时候这些连接就显得有些浪费。很多的时候数据库机器可能会支持多个应用,或者一个集群可能会有很多台应用机器。为了能这些空闲连接能够回收,就必须设置着一个配置项。这个值和minEvictableIdleTimeMillis以及numTestsPerEvictionRun会影响evictor thread的行为。默认timeBetweenEvictionRunsMillis的值是-1,就是不会运行。但是如果它设了一个不为-1的值,那么minEvictableIdleTimeMillis就不能设置的太短,默认的30分钟是个不错的选择。

 

6.配置样例

<bean id=“dataSource” class=“org.apache.commons.dbcp.BasicDataSource” destroy- method=“close”>

<property name=“driverClassName” value=“${db_driverClassName}” />

<property name=“url” value=“${db_rul}” /> 

<property name=“username” value=”${db_user}” /> 

<property name=“password” value=”${db_passwd}” />

<property name=“maxActive” value=”${db_maxActive }” />

<property name=“initialSize” value=”${db_initialSize}” />

<property name=“maxWait” value=”${db_maxWait}” />

<property name=“maxIdle” value=”${db_maxIdle }” />

<property name=“minIdle” value=”${db_minIdle}” />

<property name="timeBetweenEvictionRunsMillis" value="30000" />

<property name="testOnBorrow" value="false" />

<property name="testWhileIdle" value="true" />

<property name="validationQuery" value="select 1 from dual" />

<property name=“removeAbandoned” value=”true” />

<property name=“removeAbandonedTimeout” value=”180” />

</bean>

7.Mysql数据库的配置:

<?xml version="1.0" encoding="UTF-8"?>

<beans

xmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:p="http://www.springframework.org/schema/p"

xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"  scope="singleton" >

<property name="driverClassName">

<value>com.mysql.jdbc.Driver</value>

</property>

<property name="url">

<value>jdbc:mysql://localhost:3306/booksystem</value>

</property>

<property name="username">

<value>root</value>

</property>

<property name="password">

<value>mysqladmin</value>

</property>

<property name="maxActive">

<value>10</value>

</property>

<property name="initialSize">

<value>2</value>

</property>

</bean>

</beans>

抱歉!评论已关闭.