数据库链接池是用来保持与数据库的链接,从而便于复用。html
首先咱们须要知道程序与数据库是一个很是耗费资源的事情,尤为是程序与数据库不在同一台机器上时,必需要开启网络的链接,以及双方的互相验证等等。若是没有链接池的话,那么每次查询都要进行链接、验证、关闭等操做,会很是的耗时耗力,链接池可以保持链接,从而避免了屡次创建链接的损耗。java
上图就是一个简单的链接池的图示信息,每次程序取得链接时实际上是从链接池中取得链接,而后每次关闭的时候将此链接放入链接池中,而后链接池会本身根据一些规则定义链接在池子中保持多少、保持多久。mysql
因此从上面描述咱们能够知道在链接池中重要的就是③⑥两个步骤了,何时真正创建链接和何时真正的关闭链接。spring
其实咱们也可以本身实现一个很是简单的链接池。简单的只须要几步便可sql
public class MyDataSource implements DataSource {
private LinkedList<Connection> dataSources = new LinkedList<>();
public MyDataSource(){
//一次性建立10个链接
for(int i = 0; i < 10; i++) {
try {
createConnection();
} catch (Exception e) {
e.printStackTrace();
}
}
}
public Connection createConnection(){
Connection con = null;
//一、加载Mysql链接
try {
Class.forName("com.mysql.jdbc.Driver");
//二、经过JDBC创建数据库链接
con = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/sys", "帐号", "密码");
} catch (Exception e) {
e.printStackTrace();
}
return con;
}
@Override
public Connection getConnection(){
if (dataSources.size()>0){
return dataSources.removeFirst();
}else {
return createConnection();
}
}
public void releaseConnection(Connection connection){
dataSources.add(connection);
}
}
复制代码
固然了这只是很是简单的一个链接池实现,完整的链接池要考虑的很是多。例如经常使用的链接池配置中的几个参数,最大链接数量、空闲链接的数量、使用链接前验证链接是否可用等等。数据库
接下来咱们用一个常见的异常来回顾一下常见的数据库链接池的一些配置信息。apache
以前在开发过程当中碰到一个异常,随机出现的,异常信息以下bash
org.springframework.jdbc.support.MetaDataAccessException: Error while extracting DatabaseMetaData; nested exception is java.sql.SQLRecoverableException: Closed Connection
at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:296)
at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:320)
at org.springframework.jdbc.support.SQLErrorCodesFactory.getErrorCodes(SQLErrorCodesFactory.java:214)
复制代码
咱们的项目使用的链接时DBCP,配置以下网络
<Resource auth="Container" driverClassName="oracle.jdbc.OracleDriver" factory="org.apache.commons.dbcp.BasicDataSourceFactory" maxActive="100" maxIdle="30" maxWait="5000" name="jdbc/riskDs" password="password" type="javax.sql.DataSource" url="jdbc:oracle:thin:@ip:xxx:xxx" username="username"/>
复制代码
通过网上查询知道出现这个错误的缘由是:程序要使用数据库链接时会从线程池中拿出线程,可是此时链接池中从空闲链接中取出的线程在数据库端被断开了,在程序端并不知道此链接被断开,因此会爆此错误。固然被断开的缘由有许多,例如数据库端防火墙控制会清除链接了多久的空闲链接。oracle
因此只须要在配置文件中加入validationQuery="select 1 from dual"
这个参数便可,这个参数是在每次使用时都会验证是不是有效链接。
或者也能够加上minEvictableIdleTimeMillis="3000000"
此参数,表示空闲多久的链接会被在链接池中丢弃掉。此参数经常小于数据库端防火墙配置的清除空闲链接的时间。
若是在DBCP中配置了minEvictableIdleTimeMillis参数,也要配置testWhileIdle="true"参数,此参数是开启异步Evict的TimerTask定时线程进行控制。
经常使用的参数以下
参数 | 做用 |
---|---|
initialSize | 初始化链接池中链接数量 |
removeAbandoned | 是否自动回收超时链接 |
removeAbandonedTimeout | 超时时间 |
maxActive | 最大链接数量 |
minIdle | 最小空闲链接 |
maxIdle | 最大空闲链接 |
经常使用的这些,另外所有的话能够看DBCP官方文档说明。
其实全部的链接池的配置信息都差很少就这些参数,参数名称不同而已。