- 获取资源timeout:
异常信息如下:Caused by: java.sql.SQLException: An attempt by a client to checkout a Connection has timed out.
[Cause: com.mchange.v2.resourcepool.TimeoutException:
A client timed out while waiting to acquire a resource from com.mchange.v2.resourcepool.BasicResourcePool@4d5a39b7 -- timeout at 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、available==0(unused==0) 2、managed。size>=max(池数量已达到最大) 3、获取到的资源异常:如果设置了checkedoutTest这一项时,进行test的时候失败,导致异常;
所以更直接的原因是以下几种:
1、请求资源的队列太长,排队时间太长导致超时:线程数量应付不过来大量的请求数量,导致超时 2、testConnection的原因导致的异常:网络震荡 3、数据库服务器端无更多的链接可用
那么相应的解决方案:
1、请求资源过长的,加大maxsize,如果请求量过大的,尽量将min和max设置成一个值,因此不存在shrink和expand的操作,这也是一种性能消耗 2、testConnection设置在checkin即可,checkout时无需test,否则卡在网络震荡就不好了 3、检查数据库端的最大链接数。 4、将c3p0的debug日志打开,检查它的managed、unused、available的分别size
- deadlock