700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > 数据库连接池DBCP浅析

数据库连接池DBCP浅析

时间:2024-05-13 10:58:43

相关推荐

数据库连接池DBCP浅析

数据库|mysql教程

数据库,连接,DBCP,浅析,一个,典型关系,数据库,应

数据库-mysql教程

html5 网游 源码,vscode大型工程跳转不了,ubuntu基础,tomcat内存调优,sqlite进程,有网页设计入门步骤,数据库正则 中文,国内不备案的服务器吗,wordpress 腾讯视频插件,前端服务框架,资源爬虫搜索,php 抽象方法,seo站王,springboot读者分离,alt标签带连接, mvc 网站模板下载,mac系统网页源代码, word模板下载,html5简单后台模板,管理员管理页面代码,超市管理系统 三层架构,众筹程序源码lzw

一个典型的关系数据库应用: a. 建立连接 b. 执行数据库操作 c. 关闭连接 其中建立连接可能需要数ms才能完成。对于多并发请求的场景,频繁的建立连接、断开连接可能会成为程序与关系数据库交互的瓶颈。 为此,很多时候,我们使用数据库连接池来复用连接,避免

第三方api支付平台源码,ubuntu中usr在哪,tomcat没有详细信息,爬虫 识图软件,php文本中间,滨海新区万词霸屏seo优化公司lzw

云鹏网络源码,ubuntu网络ip配置,阿里云ecs 爬虫,php $r,seo饮食课堂lzw

一个典型的关系数据库应用:

a. 建立连接

b. 执行数据库操作

c. 关闭连接

其中建立连接可能需要数ms才能完成。对于多并发请求的场景,频繁的建立连接、断开连接可能会成为程序与关系数据库交互的瓶颈。

为此,很多时候,我们使用数据库连接池来复用连接,避免频繁的建立连接带来的资源浪费。

DBCP是应用非常广泛的关系数据库连接池,和DBCP类似的有C3p0, Proxool

DBCP依赖commons-pool提供的连接池,其包括两个不同的版本:

a. DBCP 1.4只能运行在JDK1.6(JDBC 4)

b. DBCP 1.3只能运行在JDK 1.4-1.5(JDBC 3)

DBCP相关配置:DBCP configuration

说明:

dataSource: 要连接的 datasource (通常我们不会定义在 server.xml)

defaultAutoCommit: 对于事务是否 autoCommit, 默认值为 true

defaultReadOnly: 对于数据库是否只能读取, 默认值为 false

driverClassName:连接数据库所用的 JDBC Driver Class,

maxActive: 可以从对象池中取出的对象最大个数,为0则表示没有限制,默认为8

maxIdle: 最大等待连接中的数量,设 0 为没有限制 (对象池中对象最大个数)

minIdle:对象池中对象最小个数

maxWait: 最大等待秒数, 单位为 ms, 超过时间会丟出错误信息

password: 登陆数据库所用的密码

url: 连接数据库的 URL

username: 登陆数据库所用的帐号

validationQuery: 验证连接是否成功, SQL SELECT 指令至少要返回一行

removeAbandoned: 是否自我中断, 默认是 false

removeAbandonedTimeout: 几秒后会自我中断, removeAbandoned 必须为 true

logAbandoned: 是否记录中断事件, 默认为 false

minEvictableIdleTimeMillis:大于0 ,进行连接空闲时间判断,或为0,对空闲的连接不进行验证;默认30分钟

timeBetweenEvictionRunsMillis:失效检查线程运行时间间隔,如果小于等于0,不会启动检查线程,默认-1

testOnBorrow:取得对象时是否进行验证,检查对象是否有效,默认为false

testOnReturn:返回对象时是否进行验证,检查对象是否有效,默认为false

testWhileIdle:空闲时是否进行验证,检查对象是否有效,默认为false

initialSize:初始化线程数

DBCP原理

用户使用数据库连接池流程:

a. 从连接池中获取一个连接(如果有已建立空闲的连接,直接获取连接,否则建立新连接)

b. 执行数据库操作

c. 将连接归还给数据库连接池

源码分析(common-dbcp 1.4)

BasicDataSource是用户使用的类,DBCP项目组放出example:

import javax.sql.DataSource;import java.sql.Connection;import java.sql.Statement;import java.sql.ResultSet;import java.sql.SQLException;import mons.dbcp2.BasicDataSource;public class BasicDataSourceExample { public static void main(String[] args) { // First we set up the BasicDataSource. // Normally this would be handled auto-magically by // an external configuration, but in this example well // do it manually. // System.out.println("Setting up data source."); DataSource dataSource = setupDataSource(args[0]); System.out.println("Done."); // // Now, we can use JDBC DataSource as we normally would. // Connection conn = null; Statement stmt = null; ResultSet rset = null; try { System.out.println("Creating connection."); conn = dataSource.getConnection(); System.out.println("Creating statement."); stmt = conn.createStatement(); System.out.println("Executing statement."); rset = stmt.executeQuery(args[1]); System.out.println("Results:"); int numcols = rset.getMetaData().getColumnCount(); while(rset.next()) {for(int i=1;i<=numcols;i++) { System.out.print("\t" + rset.getString(i));}System.out.println(""); } } catch(SQLException e) { e.printStackTrace(); } finally { try { if (rset != null) rset.close(); } catch(Exception e) { } try { if (stmt != null) stmt.close(); } catch(Exception e) { } try { if (conn != null) conn.close(); } catch(Exception e) { } } } public static DataSource setupDataSource(String connectURI) { BasicDataSource ds = new BasicDataSource(); ds.setDriverClassName("oracle.jdbc.driver.OracleDriver"); ds.setUsername("scott"); ds.setPassword("tiger"); ds.setUrl(connectURI); return ds; } public static void printDataSourceStats(DataSource ds) { BasicDataSource bds = (BasicDataSource) ds; System.out.println("NumActive: " + bds.getNumActive()); System.out.println("NumIdle: " + bds.getNumIdle()); } public static void shutdownDataSource(DataSource ds) throws SQLException { BasicDataSource bds = (BasicDataSource) ds; bds.close(); }}This ad is supporting your extension Smooth GesturesTurn off these ads?

用户在new 一个BasicDataSource时,并未真正建立连接池,建立连接是在用户首次使用getConnection获取连接时发生。

getConnection调用CreateDataSouce获取DataSource,其用synchronized修饰,保证同一时刻最多只有一个线程执行该段代码

如下:

public Connection getConnection() throws SQLException { return createDataSource().getConnection(); }

protected synchronized DataSource createDataSource() throws SQLException { if (closed) { throw new SQLException("Data source is closed"); } // Return the pool if we have already created it if (dataSource != null) { return (dataSource); } // 用户第一次使用getConnection请求连接时,建立数据库连接池 ConnectionFactory driverConnectionFactory = createConnectionFactory(); //建立连接池,使用commons-pool的GenericObjectPool createConnectionPool(); // Set up statement pool, if desired GenericKeyedObjectPoolFactory statementPoolFactory = null; if (isPoolPreparedStatements()) { statementPoolFactory = new GenericKeyedObjectPoolFactory(null, -1, // unlimited maxActive (per key) GenericKeyedObjectPool.WHEN_EXHAUSTED_FAIL, 0, // maxWait 1, // maxIdle (per key) maxOpenPreparedStatements); } // 设置连接池工厂 createPoolableConnectionFactory(driverConnectionFactory, statementPoolFactory, abandonedConfig); // 建立数据库连接池实例 createDataSourceInstance();// 根据配置,初始化建立一些数据库连接 try { for (int i = 0 ; i < initialSize ; i++) {connectionPool.addObject(); } } catch (Exception e) { throw new SQLNestedException("Error preloading the connection pool", e); }return dataSource; }

protected void createDataSourceInstance() throws SQLException { PoolingDataSource pds = new PoolingDataSource(connectionPool); pds.setAccessToUnderlyingConnectionAllowed(isAccessToUnderlyingConnectionAllowed()); pds.setLogWriter(logWriter); dataSource = pds; }

PoolingDataSource封装数据库连接池,其实现了getConnection,如下:

public Connection getConnection() throws SQLException { try { Connection conn = (Connection)(_pool.borrowObject()); if (conn != null) {conn = new PoolGuardConnectionWrapper(conn); } return conn; } catch(SQLException e) { throw e; } catch(NoSuchElementException e) { throw new SQLNestedException("Cannot get a connection, pool error " + e.getMessage(), e); } catch(RuntimeException e) { throw e; } catch(Exception e) { throw new SQLNestedException("Cannot get a connection, general error", e); } }

PoolableObjectFactory是生成连接池对象的工厂,其实现了makeObject,如下:

public Object makeObject() throws Exception { Connection conn = _connFactory.createConnection(); if (conn == null) { throw new IllegalStateException("Connection factory returned null from createConnection"); } initializeConnection(conn); if(null != _stmtPoolFactory) { KeyedObjectPool stmtpool = _stmtPoolFactory.createPool(); conn = new PoolingConnection(conn,stmtpool); stmtpool.setFactory((PoolingConnection)conn); } return new PoolableConnection(conn,_pool,_config); }

PoolableConnection是连接代理,其实现了close,close并不真正关闭连接,而是调用_pool.returnObject(this)将连接还给对象池:

public synchronized void close() throws SQLException { if (_closed) { // already closed return; } ...... if (!isUnderlyingConectionClosed) { // Normal close: underlying connection is still open, so we // simply need to return this proxy to the pool try {_pool.returnObject(this); // XXX should be guarded to happen at most once } catch(IllegalStateException e) { ...... }

上述borrowObject和returnObject都是GenericObjectPool提供的接口,分别用来从对象池中获取对象和归还对象。

getConnection序列图如下:

其它开源数据库连接池:C3P0、BoneCP、Proxool、阿里巴巴的Druid等

一些性能比较的文档:

c3p0、dbcp、proxool、BoneCP比较

DBCP,C3P0,Tomcat_JDBC 性能及稳定性测试

各种数据库连接池对比

reference:

commons-dbcp

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。