【发布时间】:2014-06-20 13:21:51
【问题描述】:
我有一个由 jetty + mysql 提供服务的网络应用程序。我遇到了一个问题,我的数据库连接池耗尽,所有线程都开始阻塞等待连接。我尝试了两个数据库连接池库:(1)bonecp(2)hikari。两者都与我的应用程序表现出相同的行为。
当我看到这种状态时,我已经进行了几次线程转储,并且所有被阻塞的线程都处于这种状态(不是选择bonecp,我确定它现在已经结束了):
"qtp1218743501-131" prio=10 tid=0x00007fb858295800 nid=0x669b waiting on condition [0x00007fb8cd5d3000]
java.lang.Thread.State: TIMED_WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x0000000763f42d20> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:226)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2082)
at java.util.concurrent.LinkedBlockingQueue.poll(LinkedBlockingQueue.java:467)
at com.jolbox.bonecp.DefaultConnectionStrategy.getConnectionInternal(DefaultConnectionStrategy.java:82)
at com.jolbox.bonecp.AbstractConnectionStrategy.getConnection(AbstractConnectionStrategy.java:90)
at com.jolbox.bonecp.BoneCP.getConnection(BoneCP.java:553)
at com.me.Foo.start(Foo.java:30)
...
我不知道从这里去哪里。我在想我会在线程转储中看到一些堆栈跟踪,我的代码被卡在执行一些冗长的操作,而不是等待连接。例如,如果我的代码如下所示:
public class Foo {
public void start() {
Connection conn = threadPool.getConnection();
work(conn);
conn.close();
}
public void work(Connection conn) {
.. something lengthy like scan every row in the database etc ..
}
}
我希望上面的线程之一有一个堆栈跟踪,显示它在 work() 方法中工作:
...
at com.me.mycode.Foo.work()
at com.me.mycode.Foo.start()
但他们只是在等待连接:
...
at com.jolbox.bonecp.BoneCP.getConnection() // ?
at com.me.mycode.Foo.work()
at com.me.mycode.Foo.start()
任何关于如何继续调试的想法都会很棒。
其他一些背景:应用程序正常运行大约 45 分钟,内存和线程转储显示没有异常。然后触发条件并且线程数激增。我开始认为这可能是应用程序尝试执行的 sql 语句的某种组合,这些语句在 mysql 端变成了某种锁,但我再次希望上面堆栈跟踪中的一些线程向我展示它们是在代码的那部分。
线程转储是使用 visualvm 进行的。
谢谢
【问题讨论】:
-
您是否曾尝试使用“资源尝试”来尝试您的连接逻辑?
标签: java mysql connection-pooling