Java Spring 的 C3P0 死锁

Posted

技术标签:

【中文标题】Java Spring 的 C3P0 死锁【英文标题】:C3P0 deadlock with Java Spring 【发布时间】:2017-10-30 12:31:55 【问题描述】:

我面临以下错误,并且很难调试此问题的来源。我有以下 2 个会话工厂:

<bean id="sessionFactory1"
      class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.connection.driver_class">$db.driver</prop>
            <prop key="hibernate.connection.url">$db.jdbcurl2</prop>
            <prop key="hibernate.connection.username">$db.username2</prop>
            <prop key="hibernate.connection.password">$db.password2</prop>
            <prop key="hibernate.connection.provider_class">org.hibernate.c3p0.internal.C3P0ConnectionProvider
            </prop>
            <prop key="hibernate.c3p0.min_size">1</prop>
            <prop key="hibernate.c3p0.max_size">6</prop>
            <prop key="hibernate.c3p0.maxIdleTime">3000</prop>
            <prop key="hibernate.c3p0.timeout">5000</prop>
            <prop key="hibernate.c3p0.max_statements">50</prop>
            <prop key="hibernate.c3p0.idle_test_period">3000</prop>
            <prop key="hibernate.c3p0.preferredTestQuery">SELECT 1</prop>
            <prop key="hibernate.dialect">org.hibernate.dialect.mysql5Dialect</prop>
            <prop key="hibernate.show_sql" >false</prop>
            <prop key="hibernate.format_sql" >false</prop>
            <prop key="hibernate.hbm2ddl.auto" >update</prop>
        </props>
    </property>
</bean>

<bean id="sessionFactory2"
        class="org.springframework.orm.hibernate4.LocalSessionFactoryBean" primary="true">
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.connection.driver_class">$db.driver</prop>
                <prop key="hibernate.connection.url">$db.jdbcurl</prop>
                <prop key="hibernate.connection.username">$db.username</prop>
                <prop key="hibernate.connection.password">$db.password</prop>
                <prop key="hibernate.connection.provider_class">org.hibernate.c3p0.internal.C3P0ConnectionProvider
                </prop>
                <prop key="hibernate.c3p0.min_size">1</prop>
                <prop key="hibernate.c3p0.max_size">6</prop>
                <prop key="hibernate.c3p0.maxIdleTime">3000</prop>
                <prop key="hibernate.c3p0.timeout">5000</prop>
                <prop key="hibernate.c3p0.max_statements">50</prop>
                <prop key="hibernate.c3p0.idle_test_period">3000</prop>
                <prop key="hibernate.c3p0.preferredTestQuery">SELECT 1</prop>
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
                <prop key="hibernate.show_sql" >false</prop>
                <prop key="hibernate.format_sql" >false</prop>
                <prop key="hibernate.hbm2ddl.auto" >update</prop>
            </props>
        </property>
    </bean>

以及以下连接数据:

db.driver=com.mysql.jdbc.Driver

hibernate.dialect=org.hibernate.dialect.MySQLDialect

db.jdbcurl=jdbc:mysql://localhost:3306/XXXXautoReconnect=true&allowMultiQueries=true db.username=XXXX

db.password=YYYY

db.jdbcurl2=jdbc:mysql://XXXXX-cluster.XXXXXXXX.eu-west-2.rds.amazonaws.com:3306/XXXX?autoReconnect=true&allowMultiQueries=true

db.username2=XXXX

db.password2=YYYY

这是我从日志中得到的错误消息:

    2017-10-30 12:16:25 WARN  ThreadPoolAsynchronousRunner:743 - com.mchange.v2.async.ThreadPoolAsynchronousRunner$DeadlockDetector@6cf38f72 -- APPARENT DEADLOCK!!! Creating emergency threads for unassigned pending tasks!
2017-10-30 12:16:25 WARN  ThreadPoolAsynchronousRunner:759 - com.mchange.v2.async.ThreadPoolAsynchronousRunner$DeadlockDetector@6cf38f72 -- APPARENT DEADLOCK!!! Complete Status: 
    Managed Threads: 3
    Active Threads: 3
    Active Tasks: 
        com.mchange.v2.resourcepool.BasicResourcePool$ScatteredAcquireTask@5371f5ab
            on thread: C3P0PooledConnectionPoolManager[identityToken->1bqsmig9ruavayon79lc0|319cb4da]-HelperThread-#0
        com.mchange.v2.resourcepool.BasicResourcePool$ScatteredAcquireTask@12e0b3c5
            on thread: C3P0PooledConnectionPoolManager[identityToken->1bqsmig9ruavayon79lc0|319cb4da]-HelperThread-#2
        com.mchange.v2.resourcepool.BasicResourcePool$ScatteredAcquireTask@2b726e6f
            on thread: C3P0PooledConnectionPoolManager[identityToken->1bqsmig9ruavayon79lc0|319cb4da]-HelperThread-#1
    Pending Tasks: 
        com.mchange.v2.resourcepool.BasicResourcePool$ScatteredAcquireTask@432689e8
Pool thread stack traces:
    Thread[C3P0PooledConnectionPoolManager[identityToken->1bqsmig9ruavayon79lc0|319cb4da]-HelperThread-#0,5,RMI Runtime]
        java.net.PlainSocketImpl.socketConnect(Native Method)
        java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
        java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
        java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)

我尝试将 c3p0.max_statements 设置为 0 以及许多其他方法均无效,因此如果您知道如何解决此问题,我正在寻求您的帮助。

我认为值得一提的是,当我在本地使用 2 个数据源时,一切正常。在我创建一个新的 RDS 实例并将 jdbcurl url 更改为 rds 的那一刻,我收到了上面提到的错误消息..

提前谢谢你!

【问题讨论】:

【参考方案1】:

问题是对您的 RDS 数据库的尝试挂起 - 既没有因异常而失败,也没有成功并提供异常,只是挂起。当我没有正确配置我的实例以接受来自我的客户端的连接时,我遇到了 AWS 上的连接挂起。这可能是你的问题。

测试和调试的一种方法是使用简单的测试程序,例如

import java.sql.*;

public static void main(String[] argv) 
  try 
    DriverManager.getConnection("dbc:mysql://XXXXX-cluster.XXXXXXXX.eu-west-2.rds.amazonaws.com:3306/XXXX?autoReconnect=true&allowMultiQueries=true","XXXX","YYYY").close();
    System.out.println("Successfully acquired and closed a Connection.");
  
  catch ( Exception e ) 
    e.printStackTrace();
  

如果您可以访问某种 REPL,请尝试

    DriverManager.getConnection("dbc:mysql://XXXXX-cluster.XXXXXXXX.eu-west-2.rds.amazonaws.com:3306/XXXX?autoReconnect=true&allowMultiQueries=true","XXXX","YYYY").close();

当这在您打算运行应用程序的机器上成功时,您的应用程序也可能会成功。

【讨论】:

这确实是问题所在,我已经调试了一天,仍然无法确定为什么会发生这种情况。我已经能够通过 Sequel Pro 和 MySQLWorkbench 连接到我的 RDS 实例,但不是从我的 java 程序...我的连接 url 与您的格式完全相同,但由于某种原因它超时了.. 编辑:我必须创建一个反向隧道并将 url 字符串更改为 127.0.0.1 以及将端口更改为反向隧道之一以使其在本地工作。

以上是关于Java Spring 的 C3P0 死锁的主要内容,如果未能解决你的问题,请参考以下文章

当线程全部为空时,C3P0 明显死锁?

服务器闲置一夜后的 C3P0 死锁

Spring配置c3p0数据源时出错报:java.lang.NoClassDefFoundError: com/mchange/v2/ser/Indirector

spring配置c3p0连接池

Spring 使用C3P0的时候报ClassNotFoundException: com.mchange.v2.ser.Indirector

JAVA连接池技术