`
ginge
  • 浏览: 211868 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Have you known enough about DBCP?

阅读更多

【本文如需转载,请注明作者及出处】

 


I think a lot of people have misunderstanding about DBCP. What makes them think so?
Cause' DBCP seems don't want to release database connection after use. Finally, all available connections got exhausted, and our application runs out of services.

DBCP is weak and can not bear production pressures, according to them. It’s worse that there are a lot of guys on the internet said so.


In fact, DBCP can absolutely take the job!

Firstly, its release number has reached 1.2.2. Base on the Apache Version Numbering Project's theory, any products whose version number has evolved up to 1, it is eligible to be used in production environment.

Second, I've run into such problem from my previous working experience, and my ex-colleague and I have made extensive tests on various Connection Pool products, such as Proxool, c3p0 and DBCP.
Result shows that DBCP behaves very well not only at responsiveness, stability, but also at performance. Once the network resume, it auto-reconnects instantly even after more than 8 hours network disconnection.


Third, I do the test again, but this time it’s only between DBCP and c3p0. The test starts from running 3000 to 5000 threads, which infinitely execute a query lasting at least 1 second. Effort have been made to let DBCP and C3p0 start equally, like the same initial pool size 0, the same max pool size and the same time out, etc.

 

 


Finally, I try to give you a detail introduction on the configurations of DBCP, focusing on the important parameters.

 

 All information comes from http://commons.apache.org/dbcp/configuration.html



Part1, Besides the Normal parameters:

username                           The connection username to be passed to our JDBC driver to establish a connection.

password                           The connection password to be passed to our JDBC driver to establish a connection.

url                                       The connection URL to be passed to our JDBC driver to establish a connection.

driverClassName                The fully qualified Java class name of the JDBC driver to be used.


Part2, the following are related to performances:

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

maxActive                           The maximum number of active connections that can be allocated from this pool at the same time, or non-positive for no limit.

maxIdle                              The maximum number of connections that can remain idle in the pool, without extra ones being released, or negative for no limit.

minIdle                               The minimum number of connections that can remain idle in the pool, without extra ones being created, or zero to create none.

maxWait                             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.

poolPreparedStatements    Enable prepared statement pooling for this pool.

maxOpenPreparedStatements  The maximum number of open statements that can be allocated from the statement pool at the same time, or zero for no limit.



Part3, but setting the above parameters or combining only some of the them won’t help you get rid of exhaustion of connection problem due to poorly written code, maybe that's source of problems. The following configuration matters:


validationQuery                        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.


timeBetweenEvictionRunsMillis The number of milliseconds to sleep between runs of the idle object evictor thread. When non-positive, no idle object evictor thread will be run.


minEvictableIdleTimeMillis         The minimum amount of time an object may sit idle in the pool before it is eligable for eviction by the idle object evictor (if any).


removeAbandoned Flag to remove abandoned connections if they exceed the removeAbandonedTimout. If set to true a connection is considered abandoned and eligible for removal if it has been idle longer than the removeAbandonedTimeout. Setting this to true can recover db connections from poorly written applications which fail to close a connection.


removeAbandonedTimeout Timeout in seconds before an abandoned connection can be removed. the above two parameter must be set at the same time to make connection pool manageable.If we set


validationQuery="SELECT SYSDATE FROM DUAL"
removeAbandoned=true
removeAbandonedTimeout=30
timeBetweenEvictionRunsMillis=500
minEvictableIdleTimeMillis=60000



then, we should interpreted these as:


1) If there’s poorly written code which forget to close connections after use, and it lasts for 30 seconds, it will be removed from the pool!

2) There’ll be an evictor thread up to monitor connection objects. If one of the connection objects becomes idle and last for 5000 milliseconds, it will be marked as removable. After another short nap of 500 milliseconds, that's at between 60000 and 60500 milliseconds, if the same connection is still found idle, it will be removed from the pool.



So a typical configuration for oracle would be like this:


driverClassName=driverclass
url=dburl
username=user
password=password


maxActive=100
maxWait=-1
defaultAutoCommit=true
minIdle=0
maxIdle=30
poolPreparedStatements=true

validationQuery="SELECT SYSDATE FROM DUAL"
testOnBorrow="true"
testOnReturn="false"
testWhileIdle = "false"
timeBetweenEvictionRunsMillis=500
removeAbandoned=true
removeAbandonedTimeout=30
minEvictableIdleTimeMillis=60000


1) It means when the pool starts up, poolPreparedStatements ability is enabled, transaction will be auto committed and there is no connections in it.

2) Any connections will be created on demand. If a new connection is requested, after creation, the new one will be tested against "SELECT SYSDATE FROM DUAL" before returning it to user, if it failed validation, yielding no result, the connection will be dropped, and another connection will be created and validated again until it pass.

3) If suddenly, floods of requests come in, the pool will create as many connections as it can to serve the request until the size reach 100. If requests continue to arrive, they will have wait before some connections finished the previous serving.

4) If there’s poorly written code which forget to close connections after use, and it lasts for 30 seconds, it will be removed from the pool!

5) When the flood begins to ebb, some of the connections will become idle and have nothing to do. If any connection object becomes idle and last for 60000 milliseconds, it will be marked as removable. After another short nap of 500 milliseconds, that's at between 60000 and 60500 milliseconds, if the same connection is still found idle, it will be removed from the pool.




For commons-dbcp-1.2.2 and commons-pool-1.3 and
we have to set

minIdle=0
testWhileIdle=false

to avoid a potential deadlock as described by
https://issues.apache.org/jira/browse/DBCP-44





Here is the test:

Environment:
Hardware: AMD Turion(TM) 64 X2 Mobile 1.8G    and 1.5G Memory

Operating System: Windows XP

Database:

mysql : 5.0.45-community-nt MySQL Community Edition (GPL)
Max_used_connections 100

 

 

Oracle: 10G default settings

 

Pool implementaions:

1)commons-dbcp-1.2.2(commons-pool-1.3)

2)c3p0-0.9.1.2


database  dbcp/c3p0   concurrent_threads     maxActive/poolSize   10minutes queries executed


mysql        dbcp/c3p0                5000                     100                        16200/1600
oracle       dbcp/c3p0                3000                      10                         3691/1900
oracle       dbcp/c3p0                3000                      50                         20900/6500
oracle       dbcp/c3p0                5000                      50                         8400/2000
oracle       dbcp/c3p0                5000                      80                         8800/1800

 



oracle       dbcp/c3p0                5000                       100                         ORA-12519/very slow, but no ORA-12519

(ORA-12519, TNS:no appropriate service handler found)


But if you want performance gained from dbcp, you should increase the value of "PROCESSES" parameter in oracle

 

http://www.webservertalk.com/archive149-2006-2-1410832.html 写道
PROCESSES specifies the maximum number of operating system user
processes that can simultaneously connect to Oracle. Its value should
allow for all background processes such as locks, job queue processes,
and parallel execution processes.

 




Jdbc.properties
cabernet.jdbc.driverClassName=com.mysql.jdbc.Driver
cabernet.jdbc.url=jdbc:mysql://g-mobile:3306/jbpm?useUnicode=true&characterEncoding=utf8&autoReconnect=true
cabernet.jdbc.username=root
cabernet.jdbc.password=root

#dbcp
cabernet.jdbc.maxActive=100

##max.Wait means waiting until one is available
cabernet.jdbc.maxWait=-1
cabernet.jdbc.defaultAutoCommit=true
cabernet.jdbc.minIdle=0
cabernet.jdbc.maxIdle=30
cabernet.jdbc.removeAbandoned=true
cabernet.jdbc.removeAbandonedTimeout=30
cabernet.jdbc.poolPreparedStatements=true
cabernet.jdbc.validationQuery=select current_date();
cabernet.jdbc.testOnBorrow=true
cabernet.jdbc.testOnReturn=false
cabernet.jdbc.testWhileIdle=false
cabernet.jdbc.timeBetweenEvictionRunsMillis=500
cabernet.jdbc.minEvictableIdleTimeMillis=16000
cabernet.jdbc.logAbandoned=true

#c3p0
cabernet.jdbc.acquireIncrement=5
cabernet.jdbc.idleConnectionTestPeriod=3000
cabernet.jdbc.maxIdleTime=60

###checkoutTimeout=0 means waiting until one is available
cabernet.jdbc.checkoutTimeout=0
cabernet.jdbc.maxPoolSize=100
cabernet.jdbc.minPoolSize=0
cabernet.jdbc.maxStatements=1000
cabernet.jdbc.maxStatementsPerConnection=1000
cabernet.jdbc.initialPoolSize=0
cabernet.jdbc.autoCommitOnClose=true




Test Code:

package com.cabernet.dbcp;

import java.sql.SQLException;

import javax.sql.DataSource;

import com.cabernet.BaseTestCase;

/**
 * 
 * @author ginge
 *
 */
public class TestPooling extends BaseTestCase
{
	protected DataSource	datasource;

	public void testConnection() throws SQLException, InterruptedException
	{
		for (int i = 1000; i > 0; i--)
		{
			new QueryThread(this.datasource).start();

			log.debug("PoolingThread[" + i + "] is up and running.");
		}

		while (true)
			Thread.sleep(100000);
	}

	public DataSource getDatasource()
	{
		return datasource;
	}

	public void setDatasource(DataSource datasource)
	{
		this.datasource = datasource;
	}

	@Override
	protected String[] getConfigLocations()
	{
		// TODO Auto-generated method stub
		return new String[] { "classpath*:applicationContext-resources.xml", "classpath*:applicationContext-jbpm.xml",
				"classpath*:applicationContext-hibernate.xml" };
	}

}

 

 

 

 

 

package com.cabernet.dbcp;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.Random;

import javax.sql.DataSource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * 
 * @author ginge
 *
 */
public class QueryThread extends Thread
{

	private Log		log		= LogFactory.getLog(this.getClass());
	DataSource		datasource;

	private Random	random	= new Random();

	QueryThread(DataSource datasource)
	{
		this.datasource = datasource;
	}

	@Override
	public void run()
	{
		// TODO Auto-generated method stub
		Connection connection = null;

		int i = 0;
		while (true)
		{
			if (i < Integer.MAX_VALUE)
				i++;
			else
				i = 0;

			try
			{
				connection = datasource.getConnection();
			} catch (Exception e)
			{
				log.error("getConnection exception :", e);
			}

			try
			{
				if (connection != null)
				{
					String query = "select * from jbpm_log where id_ = " + i;
					connection.createStatement().execute(query);
					log.debug("Thread[" + this.getId() + "] executeing [" + query + "]");
					sleep(1000);
					this.close(connection);
//					this.forgetToCloseSomeConnections(connection);
				}
			} catch (Exception e)
			{
				log.error("query exception :", e);
			}

		}
	}

	private void close(Connection connection)
	{
		try
		{
			connection.close();
		} catch (SQLException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	private void forgetToCloseSomeConnections(Connection connection)
	{
		if (random.nextInt(20) != 9)
			try
			{
				connection.close();
			} catch (SQLException e)
			{
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		else
		{
			if (log.isWarnEnabled())
			{
				log.warn("Connection not closed.");
			}
		}
	}
}

 

 

 

  • logs.rar (383.5 KB)
  • 描述: the test logs
  • 下载次数: 19
分享到:
评论
1 楼 dboylx 2008-03-17  
It does't release database connection after use which is not the excatly problem. It offten confuse us to identify the problem where it is , but we are also quite sure that it is not the problem. When it suddenly floods of requests come in , there is something wrong in the application and be hanged, Meanwhile, we have checked all the code in java(which is very simple code), it's fine, but not work. However,when we change the connection's pool implement like Websphere's pool , the problem is just go off.

your said that above could not persuade me to use dbcp again .

相关推荐

    DBCP依赖Jar包

    DBCP(Database Connection Pool)是Apache软件基金会的一个开源项目,全称为"Commons DBCP",它提供了一个数据库连接池服务。数据库连接池在应用服务器启动时建立一定数量的数据库连接,然后在应用程序需要时分配给...

    dbcp所需要jar

    3. **配置DBCP**:在SpringMVC中使用DBCP,首先需要将所需的jar包引入到项目中,这里提供的"dbcp所需jar"应该包含了Apache Commons DBCP的相关依赖。通常,这些依赖包括`commons-dbcp.jar`和`commons-pool.jar`。...

    开发工具 commons-dbcp2-2.1.1

    开发工具 commons-dbcp2-2.1.1开发工具 commons-dbcp2-2.1.1开发工具 commons-dbcp2-2.1.1开发工具 commons-dbcp2-2.1.1开发工具 commons-dbcp2-2.1.1开发工具 commons-dbcp2-2.1.1开发工具 commons-dbcp2-2.1.1开发...

    commons-dbcp-1.4

    Apache Commons DBCP 1.4 是一个在Java应用程序中管理数据库连接池的开源库。这个版本是在2009年发布的,它基于Jakarta DBCP项目,并且是Apache Commons的一部分,提供了一套完善的数据库连接池解决方案。Apache ...

    commons中的DBCP连接池jar

    Apache Commons DBCP(Database Connection Pool)是Java开发中常用的一个数据库连接池组件,它属于Apache Commons项目的一部分。DBCP提供了数据库连接池的功能,能够有效地管理和复用数据库连接,提高应用性能并...

    dbcp连接池常用包

    DBCP(Database Connection Pool)是Apache软件基金会的Commons项目中的一个数据库连接池组件,它提供了数据源管理和数据库连接复用的功能,以提高应用程序的性能和效率。在Java Web开发中,DBCP常用于管理数据库...

    创建dbcp连接,dbcp(Spring)

    DBCP(Database Connection Pool)是Apache Commons项目中的一个数据库连接池组件,全称为Apache Commons DBCP。它允许开发者在应用程序中实现高效的数据库连接管理,通过复用已存在的数据库连接来减少每次请求时...

    dbcp jar包 dbcp jar 包

    DBCP(Database Connection Pool)是Apache软件基金会的一个开源项目,全称为Apache Commons DBCP,它提供了一个数据库连接池的实现。数据库连接池在多线程、高并发的环境中非常关键,因为它可以有效地管理和复用...

    commons-dbcp jar包

    标题"commons-dbcp jar包"指的是Apache Commons DBCP库的Java归档(JAR)文件。这个库是Spring框架在进行数据库连接管理时的一个常用组件,尤其是在开发基于Java的企业级应用时。"spring开发的必备jar包"表明了在...

    commons-dbcp2-2.9.0-bin.zip

    DBCP(DataBase Connection Pool)是 apache common上的一个 java 连接池项目,也是 tomcat 使用的连接池组件,依赖 于Jakarta commons-pool 对象池机制,DBCP可以直接的在应用程序中使用。 使用DBCP会用到commons-...

    commons-dbcp-1.4.jar依赖包

    "commons-dbcp-1.4.jar依赖包" 指的是Apache Commons DBCP项目的一个特定版本,即1.4版本的jar文件。Apache Commons DBCP是一个开源的Java库,用于管理数据库连接池。这个标题表明我们将讨论关于DBCP的连接池服务,...

    commons-dbcp-1.2.2

    Apache Commons DBCP 1.2.2 是一个在Java应用程序中管理数据库连接池的开源库。这个版本的DBCP是Apache Commons项目的一部分,旨在提供一个健壮、高性能的数据库连接池实现,以提高Java应用的数据库访问效率。在Java...

    开源数据库连接池dbcp

    开源数据库连接池DBCP,全称为Jakarta-Commons-DBCP,是Apache软件基金会Jakarta项目中的一个组件,主要用于解决Java应用程序与数据库之间的连接管理问题。DBCP提供了一个高效且可配置的数据库连接池,使得多个...

    commons-dbcp.jar.rar

    《深入理解Apache Commons DBCP:数据库连接池的基石》 Apache Commons DBCP(Database Connection Pool)是Java世界中广泛使用的数据库连接池组件,它为应用程序提供了高效的数据库连接管理。在Java应用开发中,...

    commons-dbcp-1.4-API文档-中英对照版.zip

    赠送jar包:commons-dbcp-1.4.jar; 赠送原API文档:commons-dbcp-1.4-javadoc.jar; 赠送源代码:commons-dbcp-1.4-sources.jar; 赠送Maven依赖信息文件:commons-dbcp-1.4.pom; 包含翻译后的API文档:commons-...

    DBCP连接池DBCP和C3P0配置

    ### DBCP与C3P0连接池配置详解 #### 一、DBCP与C3P0概述 在Java开发中,数据库连接池是提高应用性能的重要手段之一。通过复用预分配好的数据库连接资源,避免了频繁创建和销毁数据库连接所带来的性能开销。Apache ...

    dbcp的jar包

    DBCP(Database Connection Pool)是Apache组织提供的一个开源数据库连接池组件,主要包含在Apache Commons DBCP项目中。这个库允许开发者管理数据库连接,通过池化的方式提高应用程序的性能和效率。DBCP是一个基于...

    commons-dbcp-1.4.zip

    Apache Commons DBCP,全称为"Database Connection Pool",是Apache软件基金会开发的一个开源项目,主要功能是提供数据库连接池的实现。这个组件是Java应用程序中管理数据库连接的有效工具,可以显著提高数据库操作...

    commons-dbcp-1.3

    Apache Commons DBCP 1.3 是一个Java数据库连接池(Connection Pool)组件,它是Apache Commons项目的一部分。这个组件主要用于管理数据库连接,提高应用程序的性能和效率。在Java应用程序中,尤其是那些处理大量...

    commons-dbcp源码

    Apache Commons DBCP(数据库连接池)是Java开发中常用的一个数据库连接管理库,它提供了数据库连接池的实现,能够有效地管理和复用数据库连接,从而提高应用的性能和效率。这个源码包"commons-dbcp-1.2.2-src"包含...

Global site tag (gtag.js) - Google Analytics