C3P0 连接池使用此配置给出连接超时错误

C3P0 connection pool gives connection timeout error with this configuration

我正在使用 resin 服务器 + spring 框架和 c3p0 连接池。 我已经使用以下属性文件配置了连接池。但是不知何故每隔 24 小时左右我的网站就会遇到连接超时错误,然后我必须重新启动我的 resin 服务器才能使网站重新上线。请告诉我以下配置文件中的错误以及我在这里缺少什么。

jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.databaseURL=jdbc:mysql://localhost/my_database1_url
jdbc.StockDatabaseURL=jdbc:mysql://localhost/my_database2_url
jdbc.username=my_username
jdbc.password=my_password
jdbc.acquireIncrement=10
jdbc.minPoolSize=20
jdbc.maxPoolSize=30
jdbc.maxStockPoolSize=30
jdbc.maxStatements=100
jdbc.numOfHelperThreads=6
jdbc.testConnectionOnCheckout=true
jdbc.testConnectionOnCheckin=true
jdbc.idleConnectionTestPeriod=30
jdbc.prefferedTestQuery=select curdate();
jdbc.maxIdleTime=7200
jdbc.maxIdleTimeExcessConnections=5

由于程序中可能存在连接泄漏的可能性(连接超时的可能原因),您需要按照以下步骤来识别泄漏。

在您的 c3p0.properties 文件中作为条目

c3p0.connectionCustomizerClassName = some.package.ConnectionLeakDetector

创建一个名为 'ConnectionLeakDetector' 的 class 并将其放入适当的包中。下面是class.

的内容
import java.sql.Connection;
import java.util.concurrent.atomic.AtomicInteger;

public class ConnectionLeakDetector implements com.mchange.v2.c3p0.ConnectionCustomizer {

    static AtomicInteger connectionCount = new AtomicInteger(0);
    @Override
    public void onAcquire(Connection c, String parentDataSourceIdentityToken)
            throws Exception {

    }

    @Override
    public void onDestroy(Connection c, String parentDataSourceIdentityToken)
            throws Exception {
    }

    @Override
    public void onCheckOut(Connection c, String parentDataSourceIdentityToken)
            throws Exception {
        System.out.println("Connections acquired: " + connectionCount.decrementAndGet());
    }

    @Override
    public void onCheckIn(Connection c, String parentDataSourceIdentityToken)
            throws Exception {
        System.out.println("Connections released: " + connectionCount.incrementAndGet());
    }

}

onCheckOut 方法会在获取连接时递增计数,而 onCheckOut 方法会在释放连接时递减计数。

执行一些场景并观察控制台上的统计信息。如果计数大于 0,则执行的场景存在连接泄漏。尝试修复它们,您将观察到差异。

作为旁注,您可以增加 jdbc.maxPoolSize 作为临时解决方案,直到您部署修复程序。

那么,一堆东西。

  • c3p0 具有用于观察和调试连接泄漏的内置工具。请设置配置参数 unusedConnectionTimeout unreturnedConnectionTimeout and debugUnreturnedConnectionStackTraces. Set an unreturnedConnectionTimeout that defines a period of time after which c3p0 should presume a Connection has leaked, and so close it. Set debugUnreturnedConnectionStackTraces to ask c3p0 to log the stack trace that checked out the Connection that did not get checked in properly. See Configuring to Debug and Workaround Broken Client Applications.
  • 您正在以非标准方式配置 c3p0。这可能很好,也可能不好,但是您想验证您打算设置的配置是 c3p0 获取的配置。 c3p0 数据源在池初始化时将其配置转储到 INFO。 请考虑检查以确保您获得了想要的配置。或者,您可以通过 JMX 检查数据源的运行时配置。
  • 除了非标准的配置方式外,您的几个配置属性似乎有问题。 prefferedTestQuery 应该是 preferredTestQuerynumOfHelperThreads 应该是 numHelperThreads.
  • 以下根本不是c3p0的配置名称。也许您在内部将它们映射到 c3p0 配置,但您想要验证这一点。以下是非 c3p0-属性-名称:

    jdbc.driverClassName=com.mysql.jdbc.Driver
    jdbc.databaseURL=jdbc:mysql://localhost/my_database1_url
    jdbc.StockDatabaseURL=jdbc:mysql://localhost/my_database2_url
    jdbc.username=my_username
    jdbc.maxStockPoolSize=30
    

    在标准的 c3p0.properties 形式中,您的意思可能是

    c3p0.driverClass=com.mysql.jdbc.Driver
    c3p0.jdbcURL=jdbc:mysql://localhost/my_database1_url
    # no equivalent -- jdbc.StockDatabaseURL=jdbc:mysql://localhost/my_database2_url
    c3p0.user=my_username
    # no equivalent -- jdbc.maxStockPoolSize=30
    

    请参阅Configuration Properties。同样,c3p0 对 jdbc. 前缀的属性一无所知,但也许您自己的库或中间件中的某些东西会选择这些属性。

注意:我喜欢看到@NiSay 检查连接泄漏的方法,因为我喜欢看到人们使用更高级的 c3p0 API。只要您不热更新数据源的配置,它就会起作用。但是你不需要那么麻烦,并且不能保证这种方法在未来的版本中会继续工作 c3p0 对 ConnectionCustomizer 生命周期没有任何承诺。 ConnectionCustomizers 旨在成为无状态的。使用 c3p0 的内置泄漏检查工具更容易、更安全,如上面第一个要点所述。