数据库连接池基础
· 没有连接池的数据库连接方式指通过 DriverManager 和基本实现 DataSource 进行连接 , 但它相关连接的建立以及关闭是非常耗时的 .
· 如果使用连接池,将有池来管理相关的数据库连接,减少对数据库连接操作 .
· 连接池所做的操作,除了管理连接,还有就是对数据库 jdbc api 的封装,但 jdbc api 才是根本 ,外面做的都是包装 , 再花哨都是假的。
c3p0 统一概念
checkout ==
从池中取得可用的连接
checkoutconnection ==
被使用的连接
checkin ==
把连接放回池中
checkinconnection ==
没有被使用的连接
所有超时设置,相关的连接,是物理连接的关闭,而不是连接返回池中
管理的是
pooledconnection
,而不是物理的
connection
pooledconnection
是
sun
针对连接池的接口,它本身包含
connection,
和这个
connection
相关的所有
statement,result,
一个
checkout
的
connection
所作的所有数据库操作,都被
pooledconnection
所管理
.
statement
缓存,主要针对
PreparedStatement
和
CallableStatement,statment
缓存主要相对一个
connection
来说的
,
不同
connection
的
statment
不能通用
.
c3p0 行为
生成一个 connnection
· 当池中 connection 没有到达最大数 , 当有请求出现 , 将会产生 connection.
· 成生一个 pooledconnection
· 通过 pooledconnection.getConnection() 得到连接 ( 得到连接是 newProxyConnection, 不是物理连接 )
checkin connection
· 与 pooledconnection 脱离关系
· 关闭与这个 connection 相关的 resultset
· 关闭所有没有缓冲的 statement.
· checkin 所有缓存的 statement.
· 修改 pooledconnection 相关信息
checkout connection
· 查看池中是否有没有使用的 connection, 有就返回
· 没有,如果没有达到最大数,就生成一个,或者就等待
omc 中 c3p0 常用配置属性
automaticTestTable
automaticTestTable
作为测试
connection
是否有效的表,如果表存在,但有记录,抛出错误,如果表不存在,则建立,并使用
SELECT * FROM automaticTestTable
作为连接测试语句
如果 automaticTestTable 没有设置,而 preferredTestQuery 设置,则使用 preferredTestQuery 作为连接测试语句
checkoutTimeout
从池中拿未使用的连接,超时设置,如果没有设置,就不超时 .
numConnections
表明池中有多少个连接
numIdleConnections
表明池中有多少个空闲连接,它们可以被 checkout
numBusyConnections
表明池中有多少个被 checkout 的连接,记住: numIdleConnections + numBusyConnections == numConnections
numUnclosedOrphanedConnections
都是 checkoutconnection, 但他们已经不再池中管理了 . 当他们 checkin 时候,将被 destory
connectionCustomizerClassName
hook
方法,在对相关资源做操作的时候,
''
他所操作的
connection
是真实的数据库连接,而不是
proxy
过的
connection''
maxIdleTime
在
checkout
一个
connection
时候,判断这个
connection
没有被使用的时间是否大于
maxIdleTime,
来决定是关闭它,还是被
checkout
maxConnectionAge
设置一个连接在池中最长的时间,如果时间超过,将会从池中清除
testConnectionOnCheckout
如果设置为
true,
每次从池中取一个连接,将做一下测试,使用
automaticTestTable
或者
preferredTestQuery,
做一条查询语句
.
看看连接好不好用,不好用,就关闭它,重新从池中拿一个
.
unreturnedConnectionTimeout
一个
checkout
连接的超时设置,一旦一个
checkout
连接超时,他将物理的关闭,而不是返回池中,主要是防止连接被长期使用不释放,这个设置也是比较危险的
idleConnectionTestPeriod
设置在池中的没有被使用的连接,是否定时做测试,看看这个连接还可以用吗?
maxStatements,maxStatementsPerConnection
缓存
statement,
一个全局的,一个是针对每一个
connection,
个人觉得效果不是很大
,
而且也使用了反射机制
.
c3p0
jconsole
说明
· sampleThreadPoolStackTraces: 打印出当前 c3p0 线程池的情况,默认是 3 个线程 ,c3p0 很多行为异步,放到线程中做的,比如 checkout,checkin,close 操作,还有内部池重新整理
· sampleThreadPoolStatus: 打印出当前 c3p0 线程池堆栈
· softResetDefaultUser: 关闭所有 checkinconnection, 重新初始化池
· hardReset: 关闭所有 checkinconnection 和 checkoutconnection, 池这个对象也不要了,全是新的 .
· close: 关闭所有跟 c3p0 相关的东西
源代码分析
生成 eclipse 项目
· 从 sourceforge 下载我们目前使用的 0 .9 .1 .2 版本 [http://nchc.dl.sourceforge.net/sourceforge/c3p0 /c3p0 -0 .9 .1 .2 .src.zip 下载 ]
· ant codegen( 因为它有很自动生成代码 )
· 导入 eclipse(source 包括 src/classes,build/codegen, 缺少 juit.jar,log4j.jar, 自己解决 )
相关概念
首先对 datasource 的理解,你可以把认为是 factory, 这样会好理解一点
·
PooledDataSource
默认情况情况下,
PooledDataSource
只管理一个连接池
(getConnection()
的时候
),
如果你使用
getConnection(username,password),
而不是默认的
username,
将会再生产一个连接池针对这个特定的用户
,
它包含一个
ConnectionPoolDataSource
实现,连接就是从
ConnectionPoolDataSource
得到的
.
·
ConnectionPoolDataSource
包名是
javax.sql,
一看就知道是
sun
定制的接口
,
表现出一个连接池
,
是
PooledConnection
的工厂
·
PooledConnection
包名是
javax.sql,
也是
sun
定制的接口
.c3p0
默认的实现是
NewPooledConnection
·
Connection,Statement,Result
操作数据库相关接口,在
c3p0
中对于
NewProxyConnection,NewProxyStatement,NewProxyResultSet,
这些东西统一被
PooledConnection
管理。
c3p0
项目情况
c3p0
是现在用的最多连接池之一,这么成功的项目却只是一个人开发的。
当目标很明确 ( 连接池要做什么,目标是非常明确的 ), 使用场景很普通的时候 , 项目能成功,完全求决于程序的架构 .
项目在 jmx 管理和本身死锁监测,做的都比较精彩,但也有它不足支持, jdk1.5 提供了很多功能(比如多线程),它很多都是自己实现了 , 这就要看作者怎么对待这个项目
目前给我的感觉有点象当年的 dom4j 感觉,毕竟都需要谋生 , 创作激情会下降的 .