使用 Spring、hibernate 和 C3P0 的设置重现 com.mysql.jdbc.exceptions.jdbc4.CommunicationsException

Posted

技术标签:

【中文标题】使用 Spring、hibernate 和 C3P0 的设置重现 com.mysql.jdbc.exceptions.jdbc4.CommunicationsException【英文标题】:Reproduce com.mysql.jdbc.exceptions.jdbc4.CommunicationsException with a setup of Spring, hibernate and C3P0 【发布时间】:2010-12-03 11:14:28 【问题描述】:

我从生产代码中得到了这个错误:

com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: 最后一个数据包成功接收 从服务器是36940秒 ago.最后一个包发送成功 到服务器是 36940 秒前, 比服务器长 'wait_timeout' 的配置值。 您应该考虑到期 和/或测试连接有效性 在您的应用程序中使用之前, 增加配置的服务器 客户端超时值,或使用 Connector/J 连接属性 'autoReconnect=true' 来避免这种情况 问题。

现在我正在尝试在本地重现问题并修复它。我将弹簧上下文设置如下:

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
    destroy-method="close" p:driverClass="com.mysql.jdbc.Driver"
    p:jdbcUrl="jdbc:mysql://localhost:3306/test?useUnicode=yes&amp;characterEncoding=UTF-8&amp"
    p:idleConnectionTestPeriod="120" p:initialPoolSize="1" p:maxIdleTime="1800"
    p:maxPoolSize="1" p:minPoolSize="1" p:checkoutTimeout="1000"
    
/>

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="hibernateProperties">
        <value>
            hibernate.connection.provider_class = org.hibernate.connection.C3P0ConnectionProvider
            hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
            hibernate.default_schema=platform_server_original
            hibernate.show_sql=false
        </value>
    </property>
    <property name="mappingResources">
        <list>
            <value>sometables.hbm.xml</value>
        </list>
    </property>
</bean>

然后我将我的mysql wait_timeout设置为10秒,然后运行我的测试,基本上是打开一个连接,做一个查询,关闭它,所以它返回到池中,然后让线程休眠15秒,然后打开再次连接,并再次进行查询,因此它将中断。但是,我只收到了类似的错误:

com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: 通讯链路故障

最后一个发送到服务器的数据包是 16 毫秒前。

所以我想知道这两个错误是相同的,还是不同的?我做了一些研究,似乎这两个错误都归结为同一个解决方案:使用属性“testConnectionOnCheckout = true”。但是,根据 c3p0 文档,这是一项非常昂贵的检查。它建议使用“idleConnectionTestPeriod”,但我已经将其设置为 120 秒。我应该使用什么值才能正确验证空闲连接?

所以我基本上要问两件事:

    如何重现生产代码中出现的错误? 我该如何解决?

谢谢!

【问题讨论】:

您最初的生产错误是指超过 10 小时的时间段,并且是在早上首次使用系统时签出连接时发生的?您不能将最小池大小设置为 0 或通过 JXB 公开池并在工作日开始之前刷新它吗? @fei - 你解决了吗?有兴趣知道结果是什么。 我最终使用了以下 2 个属性: testConnectionOnCheckout="true" preferredTestQuery="select 1" 不是最佳解决方案,但至少可以解决问题。 【参考方案1】:

我在使用 MySQL 和连接池时遇到了类似的问题。问题是您告诉连接池空闲超时为 30 分钟,但数据库在 10 秒后断开连接。由于您的空闲连接检查周期为 120 秒,因此池使用断开连接的时间还不到 110 秒!

我会使用以下设置进行生产:

MySQL:
wait_timeout=75
C3P0:
maxIdleTime=60
idleConnectionTestPeriod=55

【讨论】:

【参考方案2】:

要重现您的错误,请将您的 MySQL 属性中的连接超时设置为一个非常低的值,即 2 毫秒,然后运行一个已知处理时间较长的查询。如果您使用属性文件来设置 JDBC 连接,则可以在 MySQL 连接字符串中或通过属性设置超时属性。您可以在特定的 jaxax.sql.DataSource 连接上查找 ​​Javadocs,并在 MySQL 文档中查找有关如何执行此操作的详细信息。

【讨论】:

MySQL wait_timeout 值是秒而不是毫秒。所以不可能将其设置为 2ms ?【参考方案3】:

Fei - 可能是几件事之一,根据目前发布的信息无法真正说出。

建议您在问题中添加 MySQL/Spring/Hibernate/C3PO/JDBC 版本号,以防出现已知问题。

生产错误消息很常见,有许多可能的根本原因。为您提供一些线索:

    生产错误可能表明 你的申请不是 释放连接回 池完成后,防止 c3p0 从检查它。 (c3p0 空闲检查只能应用于 未签出的连接。)

    检查 c3p0 是否真的工作 (您可能正在使用“香草” 如果没有连接)。在你的测试中, 如果你设置(例如)MySql wait_timeout=10,应用线程 睡眠=35,和 idleConnectionTestPeriod=30,如果 池正在工作,例外 应该走开。

    关于空闲检查的费用: 考虑不使用默认值 getTables() - 可能设置 对于 MySQL 而言,preferredTestQuery 可能是便宜的(-er) 'SELECT 1'?

【讨论】:

以上是关于使用 Spring、hibernate 和 C3P0 的设置重现 com.mysql.jdbc.exceptions.jdbc4.CommunicationsException的主要内容,如果未能解决你的问题,请参考以下文章

如何使用c3p0+spring连接oracle数据库

Hibernate 与 Spring 的整合

spring5整合hibernate5出现can not resolve java..data source

spring与hibernate整合

Struts2,Spring, Hibernate三大框架SSH的整合步骤

在 Hibernate/C3P0 中处理连接池耗尽并避免死锁