- 获取资源timeout:
异常信息如下:?
1
Caused by: java.sql.SQLException: An attempt by a client to checkout a Connection has timed out.<br>[Cause: com.mchange.v2.resourcepool.TimeoutException: <br>A client timed out
while
waiting to acquire a resource from com.mchange.v2.resourcepool.BasicResourcePool
@4d5a39b7
-- timeout at awaitAvailable()
查找发现,获取connection资源timeout的地方,在basicResourcePool类的awaitAvailable方法里,代码很简单:
1 private void awaitAvailable(long timeout) throws InterruptedException, TimeoutException, ResourcePoolException
2 {
3 assert Thread.holdsLock( this );
4
5 if (force_kill_acquires)
6 throw new ResourcePoolException("A ResourcePool cannot acquire a new resource -- the factory or source appears to be down.");
7
8 Thread t = Thread.currentThread();
9 try
10 {
11 acquireWaiters.add( t );
12
13 int avail;
14 long start = ( timeout > 0 ? System.currentTimeMillis() : -1);
15 if (Debug.DEBUG && Debug.TRACE == Debug.TRACE_MAX)
16 {
17 if ( logger.isLoggable( MLevel.FINE ) )
18 logger.fine("awaitAvailable(): " +
19 (exampleResource != null ?
20 exampleResource :
21 "[unknown]") );
22 trace();
23 }
24 while ((avail = unused.size()) == 0)
25 {
26 // the if case below can only occur when 1) a user attempts a
27 // checkout which would provoke an acquire; 2) this
28 // increments the pending acquires, so we go to the
29 // wait below without provoking postAcquireMore(); 3)
30 // the resources are acquired; 4) external management
31 // of the pool (via for instance unpoolResource()
32 // depletes the newly acquired resources before we
33 // regain this‘ monitor; 5) we fall into wait() with
34 // no acquires being scheduled, and perhaps a managed.size()
35 // of zero, leading to deadlock. This could only occur in
36 // fairly pathological situations where the pool is being
37 // externally forced to a very low (even zero) size, but
38 // since I‘ve seen it, I‘ve fixed it.
39 if (pending_acquires == 0 && managed.size() < max)
40 _recheckResizePool();
41
42 this.wait(timeout);
43 if (timeout > 0 && System.currentTimeMillis() - start > timeout)
44 throw new TimeoutException("A client timed out while waiting to acquire a resource from " + this + " -- timeout at awaitAvailable()");
45 if (force_kill_acquires)
46 throw new CannotAcquireResourceException("A ResourcePool could not acquire a resource from its primary factory or source.");
47 ensureNotBroken();
48 }
49 }
50 finally
51 {
52 acquireWaiters.remove( t );
53 if (acquireWaiters.size() == 0)
54 this.notifyAll();
55 }
56 }抛出异常的是第44行,而抛出异常的先决条件就是timeout了。表象来看是这样,再继续跟进代码的时候发现,进入等待资源的先决条件是:
?
1
2
3
1
、available==
0
(unused==
0
)
2
、managed。size>=max(池数量已达到最大)
3
、获取到的资源异常:如果设置了checkedoutTest这一项时,进行test的时候失败,导致异常;
所以更直接的原因是以下几种:
?
1
2
3
1
、请求资源的队列太长,排队时间太长导致超时:线程数量应付不过来大量的请求数量,导致超时
2
、testConnection的原因导致的异常:网络震荡
3
、数据库服务器端无更多的链接可用
那么相应的解决方案:
?
1
2
3
4
1
、请求资源过长的,加大maxsize,如果请求量过大的,尽量将min和max设置成一个值,因此不存在shrink和expand的操作,这也是一种性能消耗
2
、testConnection设置在checkin即可,checkout时无需test,否则卡在网络震荡就不好了
3
、检查数据库端的最大链接数。
4
、将c3p0的debug日志打开,检查它的managed、unused、available的分别size
- deadlock
c3p0--常见异常,布布扣,bubuko.com