APPARENT DEADLOCK为未分配的待处理任务创建紧急线程

我正在使用mybatis的mysql,我在我们的实时服务器上问候这个错误

com.mchange.v2.async.ThreadPoolAsynchronousRunner$DeadlockDetector@6538f8f2 -- APPARENT DEADLOCK!!! Creating emergency threads for unassigned pending tasks! 

由于我的C3P0设置,我不明白为什么会出现这个错误? 我的C3P0设置是这样的

—-开始更新—–

下面是我的spring-servlet.xml配置

datasource bean 更新

            

从我的Dao类中我称之为mapper方法

  myDao.updateRecords() 

这是我的服务类方法

 @Override public List selectAllUsersDetail(long groupId, List ids) { List usersDetailList = null; try { usersDetailList = userDao.selectAllUsersDetail(groupId, ids); } catch (Exception e) { e.printStackTrace(); } return usersDetailList; } 

在Dao类我只是注入映射器。

 @Resource private UserMapper userMapper; @Override public List selectAllUsersDetail(long groupId, List ids) { return userMapper.selectAllUsersDetail(groupId,ids); } 

—结束更新——

如果需要任何其他信息,请告诉我。

这是完整的堆栈跟踪

 [ WARN] 2013-01-08 20:13:39 com.mchange.v2.async.ThreadPoolAsynchronousRunner$DeadlockDetector@70497e11 -- APPARENT DEADLOCK!!! Creating emergency threads for unassigned pending tasks! [ WARN] 2013-01-08 20:13:39 com.mchange.v2.async.ThreadPoolAsynchronousRunner$DeadlockDetector@70497e11 -- APPARENT DEADLOCK!!! Complete Status: Managed Threads: 3 Active Threads: 3 Active Tasks: com.mchange.v2.resourcepool.BasicResourcePool$AsyncTestIdleResourceTask@2e81b8c5 (com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#0) com.mchange.v2.resourcepool.BasicResourcePool$AsyncTestIdleResourceTask@4689a55d (com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#2) com.mchange.v2.resourcepool.BasicResourcePool$AsyncTestIdleResourceTask@76c7a0d8 (com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#1) Pending Tasks: com.mchange.v2.resourcepool.BasicResourcePool$AsyncTestIdleResourceTask@2c1101d4 com.mchange.v2.resourcepool.BasicResourcePool$AsyncTestIdleResourceTask@108f1be6 com.mchange.v2.resourcepool.BasicResourcePool$AsyncTestIdleResourceTask@2370a188 com.mchange.v2.resourcepool.BasicResourcePool$AsyncTestIdleResourceTask@377cf9e5 com.mchange.v2.resourcepool.BasicResourcePool$AsyncTestIdleResourceTask@6dfa45d8 com.mchange.v2.resourcepool.BasicResourcePool$AsyncTestIdleResourceTask@49ffa050 com.mchange.v2.resourcepool.BasicResourcePool$AsyncTestIdleResourceTask@2d760a24 Pool thread stack traces: Thread[com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#0,5,main] java.net.SocketInputStream.socketRead0(Native Method) java.net.SocketInputStream.read(SocketInputStream.java:150) java.net.SocketInputStream.read(SocketInputStream.java:121) com.mysql.jdbc.util.ReadAheadInputStream.fill(ReadAheadInputStream.java:114) com.mysql.jdbc.util.ReadAheadInputStream.readFromUnderlyingStreamIfNecessary(ReadAheadInputStream.java:161) com.mysql.jdbc.util.ReadAheadInputStream.read(ReadAheadInputStream.java:189) com.mysql.jdbc.MysqlIO.readFully(MysqlIO.java:2549) com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:3002) com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:2991) com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3532) com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2002) com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2163) com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2618) com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2568) com.mysql.jdbc.StatementImpl.executeQuery(StatementImpl.java:1557) com.mysql.jdbc.DatabaseMetaData$9.forEach(DatabaseMetaData.java:4984) com.mysql.jdbc.IterateBlock.doForAll(IterateBlock.java:51) com.mysql.jdbc.DatabaseMetaData.getTables(DatabaseMetaData.java:4962) com.mchange.v2.c3p0.impl.DefaultConnectionTester.activeCheckConnectionNoQuery(DefaultConnectionTester.java:185) com.mchange.v2.c3p0.impl.DefaultConnectionTester.activeCheckConnection(DefaultConnectionTester.java:62) com.mchange.v2.c3p0.AbstractConnectionTester.activeCheckConnection(AbstractConnectionTester.java:67) com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool$1PooledConnectionResourcePoolManager.testPooledConnection(C3P0PooledConnectionPool.java:368) com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool$1PooledConnectionResourcePoolManager.refurbishIdleResource(C3P0PooledConnectionPool.java:310) com.mchange.v2.resourcepool.BasicResourcePool$AsyncTestIdleResourceTask.run(BasicResourcePool.java:1999) com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:547) Thread[com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#2,5,main] java.net.SocketInputStream.socketRead0(Native Method) java.net.SocketInputStream.read(SocketInputStream.java:150) java.net.SocketInputStream.read(SocketInputStream.java:121) com.mysql.jdbc.util.ReadAheadInputStream.fill(ReadAheadInputStream.java:114) com.mysql.jdbc.util.ReadAheadInputStream.readFromUnderlyingStreamIfNecessary(ReadAheadInputStream.java:161) com.mysql.jdbc.util.ReadAheadInputStream.read(ReadAheadInputStream.java:189) com.mysql.jdbc.MysqlIO.readFully(MysqlIO.java:2549) com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:3002) com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:2991) com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3532) com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2002) com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2163) com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2618) com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2568) com.mysql.jdbc.StatementImpl.executeQuery(StatementImpl.java:1557) com.mysql.jdbc.DatabaseMetaData$9.forEach(DatabaseMetaData.java:4984) com.mysql.jdbc.IterateBlock.doForAll(IterateBlock.java:51) com.mysql.jdbc.DatabaseMetaData.getTables(DatabaseMetaData.java:4962) com.mchange.v2.c3p0.impl.DefaultConnectionTester.activeCheckConnectionNoQuery(DefaultConnectionTester.java:185) com.mchange.v2.c3p0.impl.DefaultConnectionTester.activeCheckConnection(DefaultConnectionTester.java:62) com.mchange.v2.c3p0.AbstractConnectionTester.activeCheckConnection(AbstractConnectionTester.java:67) com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool$1PooledConnectionResourcePoolManager.testPooledConnection(C3P0PooledConnectionPool.java:368) com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool$1PooledConnectionResourcePoolManager.refurbishIdleResource(C3P0PooledConnectionPool.java:310) com.mchange.v2.resourcepool.BasicResourcePool$AsyncTestIdleResourceTask.run(BasicResourcePool.java:1999) com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:547) Thread[com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#1,5,main] java.net.SocketInputStream.socketRead0(Native Method) java.net.SocketInputStream.read(SocketInputStream.java:150) java.net.SocketInputStream.read(SocketInputStream.java:121) com.mysql.jdbc.util.ReadAheadInputStream.fill(ReadAheadInputStream.java:114) com.mysql.jdbc.util.ReadAheadInputStream.readFromUnderlyingStreamIfNecessary(ReadAheadInputStream.java:161) com.mysql.jdbc.util.ReadAheadInputStream.read(ReadAheadInputStream.java:189) com.mysql.jdbc.MysqlIO.readFully(MysqlIO.java:2549) com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:3002) com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:2991) com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3532) com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2002) com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2163) com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2618) com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2568) com.mysql.jdbc.StatementImpl.executeQuery(StatementImpl.java:1557) com.mysql.jdbc.DatabaseMetaData$9.forEach(DatabaseMetaData.java:4984) com.mysql.jdbc.IterateBlock.doForAll(IterateBlock.java:51) com.mysql.jdbc.DatabaseMetaData.getTables(DatabaseMetaData.java:4962) com.mchange.v2.c3p0.impl.DefaultConnectionTester.activeCheckConnectionNoQuery(DefaultConnectionTester.java:185) com.mchange.v2.c3p0.impl.DefaultConnectionTester.activeCheckConnection(DefaultConnectionTester.java:62) com.mchange.v2.c3p0.AbstractConnectionTester.activeCheckConnection(AbstractConnectionTester.java:67) com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool$1PooledConnectionResourcePoolManager.testPooledConnection(C3P0PooledConnectionPool.java:368) com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool$1PooledConnectionResourcePoolManager.refurbishIdleResource(C3P0PooledConnectionPool.java:310) com.mchange.v2.resourcepool.BasicResourcePool$AsyncTestIdleResourceTask.run(BasicResourcePool.java:1999) com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:547) 

– -更新 – –

当我将p:statementCacheNumDeferredCloseThreads =“1”添加到datasouce bean时,我收到以下错误

  Error creating bean with name 'sqlSessionFactory' defined in ServletContext resource [/WEB-INF/spring-servlet.xml]: Cannot resolve reference to bean 'datasource' while setting bean property 'dataSource'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'datasource' defined in ServletContext resource [/WEB-INF/spring-servlet.xml]: Error setting property values; nested exception is org.springframework.beans.NotWritablePropertyException: Invalid property 'statementCacheNumDeferredCloseThreads' of bean class [com.mchange.v2.c3p0.ComboPooledDataSource]: Bean property 'statementCacheNumDeferredCloseThreads' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter? 

来自http://www.mchange.com/projects/c3p0/#other_ds_configuration

numHelperThreadsmaxAdministrativeTaskTime有助于配置DataSource线程池的行为。 默认情况下,每个DataSource只有三个关联的帮助程序线程。 如果性能似乎在重负载下拖拽,或者如果您通过JMX观察或直接检查PooledDataSource,那么“待处理任务”的数量通常大于零,请尝试增加numHelperThreads。 对于遇到无限期挂起的任务和“APPARENT DEADLOCK”消息的用户, maxAdministrativeTaskTime可能很有用。 (有关更多信息,请参阅附录A.)

maxAdministrativeTaskTime默认值:0在c3p0的线程池之前的秒数将尝试中断明显挂起的任务。 很少有用。 许多c3p0的函数不是由客户端线程执行的,而是由内部线程池异步执行的。 c3p0的异步直接增强了客户端性能,并通过确保在非锁定保持线程中执行慢速jdbc操作,最大限度地缩短了关键锁定所需的时间。 但是,如果这些任务中的某些任务“挂起”,那就是它们既没有成功也没有因为Exception长时间失败,c3p0的线程池可能会耗尽并且备份管理任务。 如果任务很慢,解决问题的最佳方法是通过numHelperThreads增加线程数。 但是,如果任务有时无限期挂起,则可以使用此参数强制调用任务线程的interrupt()方法(如果任务超出设定的时间限制)。 [c3p0最终将通过发出“APPARENT DEADLOCK”信号来恢复挂起的任务(您将在日志中看到它作为警告),替换线程池任务线程,并中断()原始线程。 但让游泳池进入APPARENT DEADLOCK然后恢复意味着在某些时期,c3p0的性能将受损。 因此,如果您看到这些消息, 增加numHelperThreads和设置maxAdministrativeTaskTime可能会有所帮助 。 maxAdministrativeTaskTime应该足够大,以至于任何合理的尝试从数据库获取连接,测试连接或两个销毁连接,都应该在设置的时间内成功或失败。 零(默认值)表示任务永远不会中断,这是大多数情况下最好,最安全的策略。 如果任务很慢,请分配更multithreading。 如果任务永远悬空,请尝试弄清楚原因,并且在此期间设置maxAdministrativeTaskTime可能会有所帮助。

 The default is 3 for numHelperThreads , increase this to 8-10 setting maxAdministrativeTaskTime will help 

请查看解决问题的后续步骤:

  1. 在ComboPooledDataSource中增加p:maxStatements maxStatements。

  2. p:maxStatements设置为0.例如,在Firebird中,这个hack可以使用ComboPooledDataSource。

  3. 确保在应用程序中关闭SqlSession 。 更加注意集中执行数据库操作。 在我的mySql JDBC驱动程序版本中:当对象被垃圾回收时, mysql-connector-java 5.1.8连接会自动关闭。 因此,在您的情况下,如果您不密集使用数据库,则连接不应泄漏。 不过你必须确保你是关闭myBatis SqlSession,它将jdbc连接包装到DB。

  4. 因此, JDBC3 Connection和Statement Pooling也可以尝试在c3p0配置中将statementCacheNumDeferredCloseThreads设置为1

在我的情况下,应用程序的内存太少是原因。 使用的数据库是H2或SQLite(这两个都在这个应用程序中使用)。

第一个症状是上面报告的这些WARN日志行:

 12006925 [C3P0PooledConnectionPoolManager[identityToken->2rvy8f9szmpczp1k2dm1g|33af2d37]-AdminTaskTimer] WARN com.mchange.v2.async.ThreadPoolAsynchronousRunner - com.mchange.v2.async.ThreadPoolAsynchronousRunner$DeadlockDetector@6d3a9c65 -- APPARENT DEADLOCK!!! Creating emergency threads for unassigned pending tasks! 12016284 [C3P0PooledConnectionPoolManager[identityToken->2rvy8f9szmpczp1k2dm1g|3d98d1b]-AdminTaskTimer] WARN com.mchange.v2.async.ThreadPoolAsynchronousRunner - com.mchange.v2.async.ThreadPoolAsynchronousRunner$DeadlockDetector@44565f94 -- APPARENT DEADLOCK!!! Creating emergency threads for unassigned pending tasks! 12051847 [C3P0PooledConnectionPoolManager[identityToken->2rvy8f9szmpczp1k2dm1g|5703a6aa]-AdminTaskTimer] WARN com.mchange.v2.async.ThreadPoolAsynchronousRunner - com.mchange.v2.async.ThreadPoolAsynchronousRunner$DeadlockDetector@c9f37e2 -- APPARENT DEADLOCK!!! Creating emergency threads for unassigned pending tasks! 12085128 [C3P0PooledConnectionPoolManager[identityToken->2rvy8f9szmpczp1k2dm1g|4e50d42b]-AdminTaskTimer] WARN com.mchange.v2.async.ThreadPoolAsynchronousRunner - com.mchange.v2.async.ThreadPoolAsynchronousRunner$DeadlockDetector@6f1927b7 -- APPARENT DEADLOCK!!! Creating emergency threads for unassigned pending tasks! 12085128 [C3P0PooledConnectionPoolManager[identityToken->2rvy8f9szmpczp1k2dm1g|78fa7f84]-AdminTaskTimer] WARN com.mchange.v2.async.ThreadPoolAsynchronousRunner - com.mchange.v2.async.ThreadPoolAsynchronousRunner$DeadlockDetector@22c22b50 -- APPARENT DEADLOCK!!! Creating emergency threads for unassigned pending tasks! 12172644 [C3P0PooledConnectionPoolManager[identityToken->2rvy8f9szmpczp1k2dm1g|e8e88fa]-AdminTaskTimer] WARN com.mchange.v2.async.ThreadPoolAsynchronousRunner - com.mchange.v2.async.ThreadPoolAsynchronousRunner$DeadlockDetector@745a644f -- APPARENT DEADLOCK!!! Creating emergency threads for unassigned pending tasks! 

经过很长一段时间的例外,包括揭示:

 Caused by: java.lang.OutOfMemoryError: GC overhead limit exceeded 

这个问题是可以重现的。 为应用程序提供更多内存(-Xmx8G)修复它。