我们刚刚从dbcp迁移到tomcat jdbc连接池。 我们在加载时尝试了系统并收到以下异常:
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&useDynamicCharsetInfo=false&rewriteBatchedStatements=true&useLocalSessionState=true&useLocalTransactionState=true&alwaysSendSetIsolation=false&cacheServerConfiguration=true&noAccessToProcedureBodies=true&useUnicode=true&characterEncoding=UTF-8"
username="root" validationQuery="SELECT 1"/>
env:ubuntu和tomcat 6. db - mysql
答案 0 :(得分:16)
看一下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;
}
}
因此,根据此,您的连接是 Null 。
在行上检索con
的值:
PooledConnection con = idle.poll();
如果您跟踪代码,您会看到idle
(取决于您的配置,但默认情况下)FairBlockingQueue。您可以查看提示的实现。
通常,您必须关闭ResultSet,Statements和Connections,并且已使用的连接应正确释放回池中。 不正确这样做可能导致连接从未被关闭=&gt;永远不再可用于重用(连接池“泄漏”)。
我建议你构建一些关于池状态的详细日志记录并监视它以隔离问题。
Apache的一些准则,用于防止数据库连接池泄漏:
removeAbandoned="true"
已删除并回收废弃的数据库连接
removeAbandonedTimeout="60"
设置数据库连接在被视为放弃之前处于空闲状态的秒数
logAbandoned="true"
记录放弃数据库连接资源的代码的堆栈跟踪。请记住,“记录已放弃的Connections会增加每个连接借用的开销,因为必须生成堆栈跟踪。”
我仍然认为稍微增加maxWait
值(1200,1500,1700 - 只是实验,从用户的角度来看,响应时间没有差别)将清除那些罕见的情况,在这些情况下你仍然会遇到问题
答案 1 :(得分:6)
“哪些连接不忙?”
听起来他们已被删除,并且出于某种原因,您的连接池并未尝试重新连接它们。
将此添加到您要连接的网址:
autoReconnect=true
将此属性添加到资源中会导致死连接自动重新连接。
validationQuery="SELECT 1"
此外,这应该允许您查看被删除的连接:
logAbandoned="true"
堆栈溢出有多个类似的问题。
Tomcat connection pooling,idle connections,and connection creation JDBC Connection pool not reopening Connections in tomcat
然而,也可能是你没有完全释放连接,这是他们死亡的原因。 JDBC MySql connection pooling practices to avoid exhausted connection pool
答案 2 :(得分:6)
似乎是池中的错误,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