连接池参数测试结果分析
连接池属性测试
1.initialSize属性
initialSize属性是在tomcat6.0后,连接池添加的属性,它是定义服务器启动初始化几个连接,默认情况下是0即服务器启动时不初始化连接。
2.maxActive属性
表示并发情况下最大可从连接池中获取的连接数。如果数据库不是单独,供一个应用使用,通过设置maxActive参数可以避免某个应用无限制的获取连接对其他应用造成影响,如果一个数据库只是用来支持一个应用那么maxActive理论上可以设置成该数据库可以支撑的最大连接数。maxActive只是表示通过连接池可以并发的获取的最大连接数。
3.maxIdle属性(maxActive=5,maxIdle=3)
如果在并发时达到了maxActive=5,那么连接池就必须从数据库中获取5个连接来供应用程序使用,当应用程序关闭连接后,由于maxIdle=3,因此并不是所有的连接都会归还给数据库,将会有3个连接保持在连接池种中,状态为空闲,以便下次使用时重复利用,这也是连接池真正发挥作用的地方。
4.minIdle属性
最小默认情况下并不生效,它的含义是当连接池中的连接少于minIdle,系统监控线程将启动补充功能,一般情况下不启动补充线程。
5.testOnBorrow="true"和validationQuery="select1"的属性设置
我们知道数据库连接从本质上架构在tcp/ip连接之上,一般情况下web服务器与数据库服务器都不在同一台物理机器上,而是通过网络进行连接,那么当建立数据库连接池的机器与数据库服务器自己出现网络异常时,保持在连接池中的连接将失效,不能够在次使用,传统的情况下只能通过重新启动,再次建立连接,通过设置以上两个参数,但应用程序从连接池中获取连接时,会首先进行活动性检测,当获取的连接是活动的时候才会给应用程序使用,如果连接失效,连接将释放该连接。validationQuery是一条测试语句,没有实际意义,现实中,一般用一条最为简单的查询语句充当。
6.removeAbandoned、removeAbandonedTimeout和logAbandoned属性设置
有时粗心的程序编写者在从连接池中获取连接使用后忘记了连接的关闭,这样连池的连接就会逐渐达到maxActive直至连接池无法提供服务。现代连接池一般提供一种“智能”的检查,但设置了removeAbandoned="true"时,当连接池连接数到达(getNumIdle()<2)and(getNumActive()>getMaxActive()-3)时便会启动连接回收,那种活动时间超过removeAbandonedTimeout="60"的连接将会被回收,同时如果logAbandoned="true"设置为true,程序在回收连接的同时会打印日志。
removeAbandoned是连接池的高级功能,理论上这中配置不应该出现在实际的生产环境,因为有时应用程序执行长事务,可能这种情况下,会被连接池误回收,该种配置一般在程序测试阶段,为了定位连接泄漏的具体代码位置,被开启,生产环境中连接的关闭应该靠程序自己保证。
7.Tomcatdbcp数据库连接池,在tomcat部署多个应用时,在什么情况下连接池共享,什么情况下连接池不共享?
答:把连接池配置的resource放到context中连接池针对于每个应用独立,就是说tomcat在启动时,会针对每个应用建立配置的所有连接池,有几个应用,同一个连接池就会有几个。
如果配置连接池的resource放到全局resources里即GlobalNamingResources中,连接池是共享的。就是整个tomcat无论配置多少应用,整个tomcat在启动时,针对每个配置的连接池,只会生成一个,而且每个项目共享这个连接池。修改后的xml如下:
(GlobalNamingResources在server.xml中)
<GlobalNamingResources>
<Resourcename="UserDatabase"auth="Container"
type="org.apache.catalina.UserDatabase"
description="Userdatabasethatcanbeupdatedandsaved"factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
pathname="conf/tomcat-users.xml"/>
<Resourcename="jdbc/test"auth="Container"
type="javax.sql.DataSource"
driverClassname="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/test"username="root"
password="root"maxActive="20"maxIdle="10"maxWait="1000"initialSize="10"/>
</GlobalNamingResources>
以前是在context.xml的<context></context>标签中。具体如下:
<context>
<Resourcename="jdbc/test"auth="Container"
type="javax.sql.DataSource"
driverClassname="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/test"username="root"
password="root"maxActive="20"maxIdle="10"maxWait="1000"initialSize="10"/>
</context>
但是在设置全局连接池时,必须在context.xml的context中进行引用,代码如下:
<context>
<ResourceLinkname="jdbc/test"global="jdbc/test"type="javax.sql.DataSource"/>
</context>
8.连接池里的连接,是以堆栈类型的数据结构存储还是以队列类型的数据结构存储?
答:连接池里的连接是以堆栈的形成存储的,因为经过测试,先关闭返回的连接,是后被使用的,而后关闭返回的连接先被使用,符合堆栈的先进后出的原则。
测试的Connection对象的的地址顺序,如下:
a)获得一个连接,打印Connection对象地址,关闭连接,再获得下一个,我们会发现取的是个连接都是同一个。
代码:
for(inti=0;i<10;i++){
Connectionconn=dataSource.getConnection();
System.out.println(i+":"+conn.getClass().getName()+"@"+Integer.toHexString(conn.hashCode()));
conn.close();
}
结果:
0:org.apache.tomcat.dbcp.dbcp.PoolingDataSource$PoolGuardConnectionWrapper@164b9b6
1:org.apache.tomcat.dbcp.dbcp.PoolingDataSource$PoolGuardConnectionWrapper@164b9b6
2:org.apache.tomcat.dbcp.dbcp.PoolingDataSource$PoolGuardConnectionWrapper@164b9b6
3:org.apache.tomcat.dbcp.dbcp.PoolingDataSource$PoolGuardConnectionWrapper@164b9b6
4:org.apache.tomcat.dbcp.dbcp.PoolingDataSource$PoolGuardConnectionWrapper@164b9b6
5:org.apache.tomcat.dbcp.dbcp.PoolingDataSource$PoolGuardConnectionWrapper@164b9b6
6:org.apache.tomcat.dbcp.dbcp.PoolingDataSource$PoolGuardConnectionWrapper@164b9b6
7:org.apache.tomcat.dbcp.dbcp.PoolingDataSource$PoolGuardConnectionWrapper@164b9b6
8:org.apache.tomcat.dbcp.dbcp.PoolingDataSource$PoolGuardConnectionWrapper@164b9b6
9:org.apache.tomcat.dbcp.dbcp.PoolingDataSource$PoolGuardConnectionWrapper@164b9b6
b)循环获得十个连接,将每个连接放到List集合cons里,不关闭释放这十个连接,先打印Connection对象地址。然后根据刚才放到cons里的顺序,逐个关闭设防连接,关完之后,再从连接池中获取十个连接不关闭释放,按照获取顺序,打印每一个Connection对象的地址,我们会发现,先释放的Connection对象,后没获得。
代码:
ArrayList<Connection>cons=newArrayList<Connection>();
for(inti=0;i<10;i++){
Connectionconn=dataSource.getConnection();
cons.add(conn);
System.out.println(i+":"+conn.getClass().getName()
+"@"+Integer.toHexString(conn.hashCode()));
}
for(inti=0;i<cons.size();i++){
cons.get(i).close();
}
for(inti=0;i<10;i++){
Connectionconn=dataSource.getConnection();
cons.add(conn);System.out.println(i+":"+conn.getClass().getName()
+"@"+Integer.toHexString(conn.hashCode()));
}
结果:
0:org.apache.tomcat.dbcp.dbcp.PoolingDataSource$PoolGuardConnectionWrapper@1bfbfb8
1:org.apache.tomcat.dbcp.dbcp.PoolingDataSource$PoolGuardConnectionWrapper@1c3e9ba
2:org.apache.tomcat.dbcp.dbcp.PoolingDataSource$PoolGuardConnectionWrapper@125d61e
3:org.apache.tomcat.dbcp.dbcp.PoolingDataSource$PoolGuardConnectionWrapper@10c6cfc
4:org.apache.tomcat.dbcp.dbcp.PoolingDataSource$PoolGuardConnectionWrapper@c72243
5:org.apache.tomcat.dbcp.dbcp.PoolingDataSource$PoolGuardConnectionWrapper@19a8416
6:org.apache.tomcat.dbcp.dbcp.PoolingDataSource$PoolGuardConnectionWrapper@155d3a3
7:org.apache.tomcat.dbcp.dbcp.PoolingDataSource$PoolGuardConnectionWrapper@1b994de
8:org.apache.tomcat.dbcp.dbcp.PoolingDataSource$PoolGuardConnectionWrapper@dc9766
9:org.apache.tomcat.dbcp.dbcp.PoolingDataSource$PoolGuardConnectionWrapper@57e787
0:org.apache.tomcat.dbcp.dbcp.PoolingDataSource$PoolGuardConnectionWrapper@57e787
1:org.apache.tomcat.dbcp.dbcp.PoolingDataSource$PoolGuardConnectionWrapper@dc9766
2:org.apache.tomcat.dbcp.dbcp.PoolingDataSource$PoolGuardConnectionWrapper@1b994de
3:org.apache.tomcat.dbcp.dbcp.PoolingDataSource$PoolGuardConnectionWrapper@155d3a3
4:org.apache.tomcat.dbcp.dbcp.PoolingDataSource$PoolGuardConnectionWrapper@19a8416
5:org.apache.tomcat.dbcp.dbcp.PoolingDataSource$PoolGuardConnectionWrapper@c72243
6:org.apache.tomcat.dbcp.dbcp.PoolingDataSource$PoolGuardConnectionWrapper@10c6cfc
7:org.apache.tomcat.dbcp.dbcp.PoolingDataSource$PoolGuardConnectionWrapper@125d61e
8:org.apache.tomcat.dbcp.dbcp.PoolingDataSource$PoolGuardConnectionWrapper@1c3e9ba
9:org.apache.tomcat.dbcp.dbcp.PoolingDataSource$PoolGuardConnectionWrapper@1bfbfb8