5

我们有一个使用 hibernate 作为 ORM 工具的 api,我们使用 c3p0 作为连接池处理程序。当我们处于负载状态时,我们没有问题。但是,当 api 一天左右处于非活动状态时,我们将遇到“无法获得连接”异常。因此,如果周末没有人使用该 API,我们会在周一早上收到连接错误。

原因:java.sql.SQLException:客户端检出连接的尝试已超时。

我们使用mysql作为数据库。在我的研究中,我了解到 mySQL 会在 8 小时左右后使连接失效。连接池可能会向客户端发出过时的连接,因此客户端的连接超时异常。

目前,我们没有在 C3Po 中配置任何连接测试。可以说,如果我在池将连接提供给客户端之前使用 IdleTestPeriod 测试连接。那么如果我的所有连接在某个时间点都未能通过测试会发生什么?是否会从池中删除那些失败的连接并再次生成新的活动连接?

目前,这是我们正在使用的 c3p0 设置。这个问题还有其他可能的原因吗?

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
        <property name="driverClass" value="${----}"/>
        <property name="jdbcUrl" value="${----}"/>
        <property name="user" value="${----}"/>
        <property name="password" value="${------}"/>
        <property name="minPoolSize" value="5"/>
        <property name="acquireIncrement" value="5" />
        <property name="maxPoolSize" value="125" />
        <property name="maxStatements" value="10" />
        <property name="maxIdleTime" value="180" />
        <property name="maxIdleTimeExcessConnections" value="30" />
        <property name="checkoutTimeout" value="3000" />
        <property name="preferredTestQuery" value="SELECT 1" />
    </bean>
4

2 回答 2

12

因此,您设置了 3 秒(3000 毫秒)的 checkoutTimeout。这就是您看到的异常。客户端只允许等待三秒钟从池中签出连接;如果三秒钟还不够,他们会看到您的异常。

问题是,为什么客户要花这么长时间才能获得连接?通常检查连接是一个非常快的操作。但是如果所有连接都被签出,那么客户端必须等待(缓慢)从数据库中获取连接。

您已将池配置为非常积极地剔除连接。如果超过 maxIdleTimeExcessConnections=30 秒,任何数量超过 minPoolSize=5 的连接都将被销毁。然而,您的池已配置为大规模爆发:maxPoolSize=125。假设您的应用程序安静了一段时间,然后收到来自客户端的大量连接请求。池将很快用完 Connections 并开始获取,在 acquireIncrement=5 的突发中。但是如果突然有 25 个客户端并且池中只有 5 个连接,那么第 25 个客户端在获取连接之前可能会超时并非不可能。

你可以做很多事情。这些调整是可分离的,您可以根据需要混合或匹配。

  1. 不那么积极地剔除空闲的“多余”连接,因此一般来说,您的池具有服务突发请求的能力。您可能会完全放弃 maxIdleTimeExcessConnections,并在 maxIdleTime=180 秒不使用后让 Connections 慢慢枯萎。(不利的一面?在不活动期间,更大的资源占用时间更长。)

  2. 将 minPoolSize 设置为更高的值,这样池就不太可能看到连接太少的活动爆发。(缺点?更大的永久资源占用。)

  3. 从您的配置中删除 checkoutTimeout。c3p0 的默认设置是允许客户端无限期地等待连接。(缺点?也许你更喜欢客户快速报告失败而不是等待可能的成功。)

我认为您观察到的问题与连接测试或 MySQL 超时本身没有太大关系,但这并不意味着您不应该处理这些问题。我会听从 nobeh 关于 MySQL 重新连接问题的建议。(我不是 MySQL 的大用户。)您应该考虑实施连接测试。你有一个preferredTestQuery,所以测试应该相当快。我通常的选择是使用 testConnectionOnCheckin 和 idleConnectionTestPeriod。见http://www.mchange.com/projects/c3p0/#configuring_connection_testing

祝你好运!

于 2012-07-31T18:04:19.183 回答
1

MySQL Java Connector中的高可用性和集群部分中,查看属性;特别是和。使用 JDBC 连接 URL 中的属性。他们以前在使用 MySQL、Hibernate 和 C3P0 时帮助过我。希望这会有所帮助。autoReconnectautoReconnetForPools

于 2012-07-31T16:22:03.217 回答