在tomcat jdbc连接池中缺less连接

我们刚刚从dbcp迁移到tomcat jdbc连接池。 我们在加载的时候试过这个系统,并收到以下exception:

java.sql.SQLException: [IA1856] Timeout: Pool empty. Unable to fetch a connection in 1 seconds, none available[size:125; busy:90; idle:0; lastwait:1000]. at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:632) at org.apache.tomcat.jdbc.pool.ConnectionPool.getConnection(ConnectionPool.java:174) at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:124) at com.inneractive.model.mappings.BasicPersistenceEntityMapping.getConnection(BasicPersistenceEntityMapping.java:233) at com.inneractive.model.mappings.BasicPersistenceEntityMapping.callWithConnection(BasicPersistenceEntityMapping.java:243) at com.inneractive.model.mappings.PersistenceEntityMapping.get(PersistenceEntityMapping.java:194) at com.inneractive.model.data.client.ClientUtils.GetClientByExamples(ClientUtils.java:353) at com.inneractive.client.ExternalAdRingsClientStart.getClientInfoByRequestParametersOrInsert(ExternalAdRingsClientStart.java:1329) at com.inneractive.client.ExternalAdRingsClientStart.newClientSession(ExternalAdRingsClientStart.java:245) at com.inneractive.simpleM2M.web.SimpleM2MProtocolBean.generateCampaign(SimpleM2MProtocolBean.java:235) at com.inneractive.simpleM2M.web.SimpleM2MProtocolBean.generateCampaign(SimpleM2MProtocolBean.java:219) at com.inneractive.simpleM2M.web.AdsServlet.doGet(AdsServlet.java:175) at javax.servlet.http.HttpServlet.service(HttpServlet.java:617) at javax.servlet.http.HttpServlet.service(HttpServlet.java:717) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:555) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298) at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:859) at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588) at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:396) at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) at java.lang.Thread.run(Thread.java:662) 

注意这个:

 [size:125; busy:90; idle:0; lastwait:1000] 

哪里的连接不忙? 在这之后,忙碌的人数不断下降,但我们仍然没有设法得到任何连接。

有任何想法吗?

组态:

 <Resource auth="Container" driverClassName="com.mysql.jdbc.Driver" factory="org.apache.tomcat.jdbc.pool.DataSourceFactory" loginTimeout="10000" maxActive="35" maxIdle="35" maxWait="1000" name="jdbc/mysql" password="-----" testOnBorrow="true" testOnReturn="false" type="javax.sql.DataSource" url="jdbc:mysql://localhost:3306/my_db?elideSetAutoCommits=true&amp;useDynamicCharsetInfo=false&amp;rewriteBatchedStatements=true&amp;useLocalSessionState=true&amp;useLocalTransactionState=true&amp;alwaysSendSetIsolation=false&amp;cacheServerConfiguration=true&amp;noAccessToProcedureBodies=true&amp;useUnicode=true&amp;characterEncoding=UTF-8" username="root" validationQuery="SELECT 1"/> 

env:ubuntu和tomcat 6. db – mysql

看看ConnectionPool.java的源代码,你可能会在borrowConnection()方法中找到这个代码片段:

  //we didn't get a connection, lets see if we timed out if (con == null) { if ((System.currentTimeMillis() - now) >= maxWait) { throw new SQLException("[" + Thread.currentThread().getName()+"] " + "Timeout: Pool empty. Unable to fetch a connection in " + (maxWait / 1000) + " seconds, none available["+busy.size()+" in use]."); } else { //no timeout, lets try again continue; } } 

所以根据这个,你的连接是空的

con的值在线上检索:

 PooledConnection con = idle.poll(); 

如果你跟踪代码,你会看到idle (取决于你的配置,但默认情况下) FairBlockingQueue 。 你可以检查提示的实现。

一般情况下,您总是必须关闭ResultSet,Statements和Connections,并且使用的连接应该正确地释放回池中。 不正确的做法可能会导致连接永远不会被关闭=>永远不能重新使用(连接池“泄漏”)。

我建议你在池的状态上建立一些详细的日志记录并监视它以隔离问题。

Apache为防止数据库连接池泄漏提供了一些指导:

 removeAbandoned="true" 

废弃的数据库连接被删除并回收

 removeAbandonedTimeout="60" 

设置数据库连接在被视为放弃之前闲置的秒数

 logAbandoned="true" 

记录放弃数据库连接资源的代码的堆栈跟踪。 请记住,“由于必须生成堆栈跟踪,所以”废弃的连接的日志记录会增加每个连接借用的开销“。

我仍然认为稍微增加maxWait值( maxWait – 只是试验,从用户角度来看响应时间没有差异)将清除那些你仍然有问题的罕见情况。

“不忙的连接在哪里?”

这听起来像他们已经被删除,由于某种原因,您的连接池不尝试重新连接它们。

将其添加到您要连接到的URL:

 autoReconnect=true 

并将此作为属性添加到资源应导致死连接自动重新连接。

 validationQuery="SELECT 1" 

这也应该让你看到连接被丢弃:

 logAbandoned="true" 

堆栈溢出有多个类似的问题。

Tomcat连接池,空闲连接和连接创建 JDBC连接池不重新连接tomcat中的连接

然而,也可能是因为你没有完全释放这些导致死亡的原因。 JDBC MySql连接池的做法可以避免耗尽连接池

似乎是在池中的一个bug, size变量增加,然后尝试创建连接,但如果创建失败…我们有size值大,没有实际的连接池 – 可怕的:

  //if we get here, see if we need to create one //this is not 100% accurate since it doesn't use a shared //atomic variable - a connection can become idle while we are creating //a new connection if (size.get() < getPoolProperties().getMaxActive()) { //atomic duplicate check if (size.addAndGet(1) > getPoolProperties().getMaxActive()) { //if we got here, two threads passed through the first if size.decrementAndGet(); } else { //create a connection, we're below the limit return createConnection(now, con, username, password); } } //end if