开发的系统使用了Spring JdbcTemplate +
c3p0组合,在做性能测试的时候出现了严重的性能问题。40的并发访问,开始的时候系统正常,等过了几分钟后,应用程序不能访问了。停止40并发的压力
后,过1分钟左右又可以正常访问应用程序了,很迷茫。后台log文件有警告信息:
2011-11-01 13:48:39,378 [com.mchange.v2.async.ThreadPoolAsynchronousRunner:435]
-[WARN] com.mchange.v2.async.ThreadPoolAsynchronousRunner$DeadlockDetector@4ec5571b
-- APPARENT DEADLOCK!!!
Complete Status: [num_managed_threads: 10, num_active: 10; activeTasks: com.mchange.v2.resourcepool.BasicResourcePool$AcquireTask@7dd9d603 (com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#6), com.mchange.v2.resourcepool.BasicResourcePool$AcquireTask@68719f81 (com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#9), com.mchange.v2.resourcepool.BasicResourcePool$AcquireTask@7b9f03b8 (com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#7),
把c3p0换为DBCP后,系统可以正常进行性能测试,访问正常,判定c3p0存在bug。
上网查找资料,发现很多人也遇到了"APPARENT DEADLOCK"的问题
http://www.iteye.com/topic/71051
http://www.iteye.com/topic/22160
http://www.iteye.com/topic/87313
http://www.iteye.com/topic/429677
https://forum.hibernate.org/viewtopic.php?f=1&t=947246&sid=ad2b8cc3213c9dac834d81b55bbf6291
没有找到解决答案,但是基本了解了c3p0的运行原理。c3p0在从连接池中获取和返回连接的时候,采用了异步的处理方式,使用一个线程池来异步的
把返回关闭了(没有真正关闭)的连接放入连接池中。这样就意味着,我们在调用了从c3p0获得的连接的close方法时,不是立即放回池中的,而是放入一
个事件队列中等待c3p0内部的线程池顺序的处理。
c3p0中有2个参数和内部的连接池有关,分别是:
其含义的官方描述在:
http://www.mchange.com/projects/c3p0/index.html
其中通过查看c3p0的源码,可以看出那些功能是需要内部线程池处理的:
expandPool -- 在扩大池中连接的时候,如管理的连接从20扩大到40个
shrinkPool -- 在缩小连接池的时候,这个过程需要真正关闭一些连接
doCheckinManaged -- 把连接返回给连接池
checkIdleResources -- 定时检查池中的连接
遇到上面的“APPARENT DEADLOCK”警告就是由于c3p0内部线程池的所有线程都被挂起而造成的,因此官方文档说把仔细查看log日志,会发现都是那些任务占据了宝贵的线程:
[com.mchange.v2.async.ThreadPoolAsynchronousRunner:435]-[WARN] com.mchange.v2.async.ThreadPoolAsynchronousRunner$DeadlockDetector@4ec5571b
-- APPARENT DEADLOCK!!! Complete Status: [num_managed_threads: 10, num_active: 10;
activeTasks:
com.mchange.v2.resourcepool.BasicResourcePool$AcquireTask@7dd9d603 (com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#6),
com.mchange.v2.resourcepool.BasicResourcePool$AcquireTask@68719f81 (com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#9),
com.mchange.v2.resourcepool.BasicResourcePool$AcquireTask@7b9f03b8 (com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#7),
com.mchange.v2.resourcepool.BasicResourcePool$AcquireTask@4ad6470 (com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#4),
com.mchange.v2.resourcepool.BasicResourcePool$AcquireTask@139cf776 (com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#0),
com.mchange.v2.resourcepool.BasicResourcePool$AcquireTask@263a6e09 (com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#2),
com.mchange.v2.resourcepool.BasicResourcePool$AcquireTask@460e247a (com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#3),
com.mchange.v2.resourcepool.BasicResourcePool$AcquireTask@4a7ce984 (com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#1),
com.mchange.v2.resourcepool.BasicResourcePool$AcquireTask@4ec6ff50 (com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#5),
com.mchange.v2.resourcepool.BasicResourcePool$AcquireTask@6aa40597 (com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#8);
pendingTasks:
com.mchange.v2.resourcepool.BasicResourcePool$6@366b3333,
com.mchange.v2.resourcepool.BasicResourcePool$AcquireTask@37ee752e,
com.mchange.v2.resourcepool.BasicResourcePool$AcquireTask@84f3bb2,
com.mchange.v2.resourcepool.BasicResourcePool$6@9d82761,
com.mchange.v2.resourcepool.BasicResourcePool$AcquireTask@4e015653,
com.mchange.v2.resourcepool.BasicResourcePool$AcquireTask@39ca8b27,
com.mchange.v2.resourcepool.BasicResourcePool$6@2075cb15,
com.mchange.v2.resourcepool.BasicResourcePool$AcquireTask@1567e059,
com.mchange.v2.resourcepool.BasicResourcePool$6@56b9fe09,
可以看到AcquireTask占用了内部线程池的所有线程,没有线程可以来执行BasicResourcePool$6对应的任务,而这个任务的作用就是把池外使用完的连接放回池内的,c3p0被挂起了。
我的解决方法是用单独的线程来处理“归还”连接的任务,因为这个任务的优先级最高,而且耗费的时间很短。
上传我修改后的 c3p0 jar包,只改了一个文件:BasicResourcePool
分享到:
相关推荐
c3p0存在严重bug,解决AcquireTask占用了内部线程池的所有线程,没有线程可以来执行BasicResourcePool$6对应的任务,而这个任务的作用就是把池外使用完的连接放回池内的,c3p0被挂起了问题。
c3p0是款强大的数据库连接池 其完整包要到官网下载 第一次使用学习的同学一定很是头大!因为不知道怎么写xml环境配置文件 所以本人稍微做了整理 里面有样板的xml配置文件 注意:1 配置文件名不能乱改(否则c3p0会找不到...
c3p0 重新自动连接c3p0 重新自动连接c3p0 重新自动连接c3p0 重新自动连接
C3p0c3p0-0.9.5.5三个jar包使用,匹配mysql8.0等信息,包含mchange-commons-java-0.2.19.jar、c3p0-oracle-thin-extras-0.9.5.5.jar、c3p0-0.9.5.5.jar
赠送jar包:c3p0-0.9.5.2.jar; 赠送原API文档:c3p0-0.9.5.2-javadoc.jar; 赠送源代码:c3p0-0.9.5.2-sources.jar; 赠送Maven依赖信息文件:c3p0-0.9.5.2.pom; 包含翻译后的API文档:c3p0-0.9.5.2-javadoc-API...
java中c3p0数据库连接池使用方法(c3p0-config.xml+c3p0-0.9.2-pre1.jar+JdbcPool_c3p0.java),里面包含了c3p0-0.9.2-pre1.jar、以及配置文件:c3p0-config.xml、以及一个c3p0数据库连接池工具类(只有简单的两个方法...
C3P0源码及实例:C3P0资源文件配置、XML文件配置 C3P0源码及实例:C3P0资源文件配置、XML文件配置
C3P0数据库连接池和jar包,因为jdbc没有保持连接的能力,一旦超过一定时间没有使用(大约几百毫秒),连接就会被自动释放掉。而每次新建连接都需要140毫秒左右的时间,所以耗费时间比较多。若使用C3P0连接池来池化...
c3p0连接池,java jdbc操作
c3p0配置文件
c3p0 jar包c3p0 jar包c3p0 jar包c3p0 jar包c3p0 jar包c3p0 jar包c3p0 jar包c3p0 jar包c3p0 jar包c3p0 jar包c3p0 jar包
c3p0配置文件
c3p0-0.9.5.1 jar包
C3P0是一个开源的JDBC连接池,它实现了数据源和JNDI绑定,支持JDBC3规范和JDBC2的标准扩展。目前使用它的开源项目有Hibernate,Spring等。C3P0数据源在项目开发中使用得比较多。导入相关jar包c3p0-0.9.2-pre1.jar、...
C3P0相关的JAR包,数据库连接池所依赖的三个JAR包
c3p0-0.9.2.1.jar&&hibernate-c3p0-4.0.0.Final[1].jar&&mchange-commons-java-0.2.3.4.jar
C3P0 是最常用的连接池技术!Spring框架,默认支持C3P0连接池技术!
c3p0和dbutils的jar包c3p0和dbutils的jar包c3p0和dbutils的jar包c3p0和dbutils的jar包c3p0和dbutils的jar包c3p0和dbutils的jar包c3p0和dbutils的jar包c3p0和dbutils的jar包c3p0和dbutils的jar包c3p0和dbutils的jar包...
c3p0连接池jar包
C3P0连接池配置详解C3P0连接池配置详解C3P0连接池配置详解C3P0连接池配置详解