数据库连接池

计算机网络中的连接池的概念:局域网内部用户数量巨大,但只有几个外部IP地址。因为不是所有用户都要同时上网,当一个用户需要上网的时候,可以从连接池中获取一个外部IP地址从而对外进行上网;不再需要的时候,这个外部IP地址被放回连接池,给其他用户使用。

数据库中也存在连接池,主要是通过对连接的复用,从而更加高效的实现了对用户请求的响应

数据库连接池技术的原理:连接复用;对JDBC中的原始连接进行了封装,方便应用对连接的使用,提高开发效率。由三部分组成:连接池的建立、连接池中连接的使用治理连接池的关闭。

连接池的建立:

应用程序中建立的连接池其实是一个静态的。所谓静态连接池是指连接池中的连接在系统初始化时就已分配好,且不能随意关闭连接。Java中提供了很多容器类可以方便的构建连接池,如:Vector、Stack、Servlet、Bean等,通过读取连接属性文件Connections.properties与数据库实例建立连接。在系统初始化时,根据相应的配置创建连接并放置在连接池中,以便需要使用时能从连接池中获取,这样就可以避免连接随意的建立、关闭造成的开销。

连接池的治理:

Reference Counting(引用记数)设计模式。该模式在复用资源方面应用的非常广泛,把该方法运用到对于连接的分配释放上,为每一个数据库连接,保留一个引用记数,用来记录该连接的使用者的个数

具体实现:

当客户请求数据库连接时,首先查看连接池中是否有空闲连接(指当前没有分配出去的连接)。假如存在空闲连接,则把连接分配给客户并作相应处理(即标记该连接为正在使用,引用计数加1)。假如没有空闲连接,则查看当前所开的连接数是不是已经达到maxConn(最大连接数),假如没达到就重新创建一个连接给请求的客户;假如达到就按设定的maxWaitTime(最大等待时间)进行等待,假如等待maxWaitTime后仍没有空闲连接,就抛出无空闲连接的异常给用户。

当客户释放数据库连接时,先判定该连接的引用次数是否超过了规定值,假如超过就删除该连接,并判定当前连接池内总的连接数是否小于minConn(最小连接数),若小于就将连接池布满;假如没超过就将该连接标记为开放状态,可供再次复用。

连接池的关闭:

当应用程序退出时,应关闭连接池,此时应把在连接池建立时向数据库申请的连接对象统一归还给数据库(即关闭所有数据库连接),这与连接池的建立正好是一个相反过程。

连接池的配置:

应该在开发的过程中设定较小minConn,而在实际应用的中设定较大minConn。为此在连接池类ConnectionPool中加入两个方法getActiveSize()和getOpenSize(),ActiveSize 表示某一时间有多少连接正被使用,OpenSize表示连接池中有多少连接被打开,反映了连接池使用的峰值。将这两个值在日志信息中反应出来, minConn的值应该小于平均ActiveSize,而maxConn的值应该在activeSize和OpenSize之间

DBCP:是apache的一个java连接池项目,是tomcat的连接池组件。单独使用需要 common-dbcp.jar,common-pool.jar,common-collections.jar.       三个包

java代码:

 1 public class DBCPUtils {  
 2     private static DBCPUtils dbcputils=null;  
 3     private BasicDataSource bds=null;  
 4     private DataSourceConnectionFactory dscf=null;  
 5     private DBCPUtils(){  
 6         if(bds==null)  
 7             bds=new BasicDataSource();  
 8           
 9         bds.setUrl(DBConsts.url);  
10         bds.setUsername(DBConsts.username);  
11         bds.setPassword(DBConsts.password);  
12         bds.setDriverClassName(DBConsts.driverclass);  
13           
14         bds.setMaxActive(100);  
15         bds.setInitialSize(20);  
16         bds.setMaxIdle(20);  
17         bds.setMinIdle(10);  
18           
19         dscf=new DataSourceConnectionFactory(bds);  
20     }  
21     public synchronized static DBCPUtils getInstance(){  
22         if(dbcputils==null)  
23             dbcputils=new DBCPUtils();  
24         return dbcputils;  
25     }  
26     public Connection getConnection(){  
27         Connection con=null;  
28         try {  
29             con=(Connection)dscf.createConnection();  
30         } catch (SQLException e) {  
31             // TODO Auto-generated catch block  
32             e.printStackTrace();  
33         }  
34         return con;  
35     }  
36       
37     public static void main(String[] args) throws SQLException {  
38         Connection con=null;  
39         long begin=System.currentTimeMillis();  
40         for(int i=0;i<1000000;i++){  
41             con=DBCPUtils.getInstance().getConnection();  
42             con.close();  
43         }     
44         long end=System.currentTimeMillis();  
45         System.out.println("耗时为:"+(end-begin)+"ms");  
46     }  
47 }  
View Code

C3P0:是一个开放源码的JDBC连接池。在使用时需要导入c3p0-*.jar包。

 1 public class C3P0Utils {  
 2     private static C3P0Utils dbcputils=null;  
 3     private ComboPooledDataSource cpds=null;  
 4     private C3P0Utils(){  
 5         if(cpds==null){  
 6             cpds=new ComboPooledDataSource();  
 7         }  
 8         cpds.setUser(DBConsts.username);  
 9         cpds.setPassword(DBConsts.password);  
10         cpds.setJdbcUrl(DBConsts.url);  
11         try {  
12             cpds.setDriverClass(DBConsts.driverclass);  
13         } catch (PropertyVetoException e) {  
14             // TODO Auto-generated catch block  
15             e.printStackTrace();  
16         }  
17         cpds.setInitialPoolSize(100);  
18         cpds.setMaxIdleTime(20);  
19         cpds.setMaxPoolSize(100);  
20         cpds.setMinPoolSize(10);  
21     }  
22     public synchronized static C3P0Utils getInstance(){  
23         if(dbcputils==null)  
24             dbcputils=new C3P0Utils();  
25         return dbcputils;  
26     }  
27     public Connection getConnection(){  
28         Connection con=null;  
29         try {  
30             con=cpds.getConnection();  
31         } catch (SQLException e) {  
32             // TODO Auto-generated catch block  
33             e.printStackTrace();  
34         }  
35         return con;  
36     }  
37       
38     public static void main(String[] args) throws SQLException {  
39         Connection con=null;  
40         long begin=System.currentTimeMillis();  
41         for(int i=0;i<1000000;i++){  
42             con=C3P0Utils.getInstance().getConnection();  
43             con.close();  
44         }     
45         long end=System.currentTimeMillis();  
46         System.out.println("耗时为:"+(end-begin)+"ms");  
47     }  
48 }  
View Code

数据库连接的常量值:

1 public class DBConsts {  
2     public static final String url="jdbc:mysql://localhost:3306/deys";  
3     public static final String username="root";  
4     public static final String password="";  
5     public static final String driverclass="com.mysql.jdbc.Driver";  
6       
7 }  
View Code

DBCP有着比C3P0更高的效率,但是实际应用中,DBCP可能出现丢失连接的可能,而C3P0稳定性较高。因此在实际应用中,C3P0使用较为广泛

maxWait:获取连接等待超时时间

MaxActive,连接池的最大数据库连接数。设为0表示无限制。   ms---单位

maxIdle:连接池中数据库连接的最大的空闲连接数。设为0表示无限制。

两者区别
dbcp没有自动的去回收空闲连接的功能 c3p0有自动回收空闲连接功能
两者主要是对数据连接的处理方式不同!C3P0提供最大空闲时间,DBCP提供最大连接数。
前者当连接超过最大空闲连接时间时,当前连接就会被断掉DBCP当连接数超过最大连接数时,所有连接都会被断开

DruidDataSource:
 1 <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> 
 2       <!-- 基本属性 url、user、password -->
 3       <property name="url" value="${jdbc.url}" />
 4       <property name="username" value="${jdbc.user}" />
 5       <property name="password" value="${jdbc.password}" />
 6 
 7       <!-- 配置初始化大小、最小、最大 -->
 8       <property name="initialSize" value="1" />
 9       <property name="minIdle" value="1" /> 
10       <property name="maxActive" value="20" />
11 
12       <!-- 配置获取连接等待超时的时间 -->
13       <property name="maxWait" value="60000" />
14 
15       <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
16       <property name="timeBetweenEvictionRunsMillis" value="60000" />
17 
18       <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
19       <property name="minEvictableIdleTimeMillis" value="300000" />
20 
21       <property name="validationQuery" value="SELECT 'x'" />
22       <property name="testWhileIdle" value="true" />
23       <property name="testOnBorrow" value="false" />
24       <property name="testOnReturn" value="false" />
25 
26       <!-- 打开PSCache,并且指定每个连接上PSCache的大小 -->
27       <property name="poolPreparedStatements" value="true" />
28       <property name="maxPoolPreparedStatementPerConnectionSize" value="20" />
29 
30       <!-- 配置监控统计拦截的filters -->
31       <property name="filters" value="stat" /> 
32   </bean>
View Code
1 jdbc.dbType=mysql
2 jdbc.url=jdbc:mysql://182.92.152.53:3306/xiaoyou?useUnicode=true&characterEncoding=utf-8
3 jdbc.driverClass=com.mysql.jdbc.Driver
4 jdbc.user=root
5 jdbc.password=gwy307
6 jdbc.initialPoolSize=1
7 jdbc.minPoolSize=1
8 jdbc.maxPoolSize=30
View Code

优点:内置filter插件。可以监控数据库访问性能。

支持数据库密码加密

SQL执行日志

扩展JDBC,如果你要对JDBC层有编程的需求,可以通过Druid提供的Filter机制,很方便编写JDBC层的扩展插件。

Druid监控:

1 <!-- Druid监控Servlet -->
2 <servlet>
3     <servlet-name>DruidStatView</servlet-name>
4     <servlet-class>com.alibaba.druid.support.http.StatViewServlet</servlet-class>
5 </servlet>
6 <servlet-mapping>
7     <servlet-name>DruidStatView</servlet-name>
8     <url-pattern>/druid/*</url-pattern>
9 </servlet-mapping>
View Code

通过访问druid/index.html 可以查看项目的运行情况,也可以分析SQL语句的执行情况,便于调优

 
原文地址:https://www.cnblogs.com/dobestself-994395/p/4381378.html