首页 > 代码库 > c3p0--常见异常

c3p0--常见异常

  1. 获取资源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
  2. deadlock