alibaba / druid

阿里云计算平台DataWorks(https://help.aliyun.com/document_detail/137663.html) 团队出品,为监控而生的数据库连接池
https://github.com/alibaba/druid/wiki
Apache License 2.0
27.93k stars 8.57k forks source link

Caused by: com.alibaba.druid.pool.DataSourceClosedException: dataSource already closed #1625

Open shangdiyisi opened 7 years ago

shangdiyisi commented 7 years ago

我的项目用到了spring的taskExecutor mybatis和druid。我只知道如果在taskExecutor中执行任务时,偶尔会出现这个问题 。 不知道该如何下手处理

shangdiyisi commented 7 years ago

taskExecutor执行的任务涉及网络请求,请求失败了还有失败重试,所以耗时可能会比较久

shangdiyisi commented 7 years ago
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
    init-method="init" destroy-method="close">
    <property name="url" value="${jdbc.url}" />
    <property name="username" value="${jdbc.username}" />
    <property name="password" value="${jdbc.password}" />
    <property name="filters" value="stat" />
    <property name="maxActive" value="1024" />
    <property name="initialSize" value="32" />
    <property name="minIdle" value="2" />
    <property name="maxWait" value="10000" />
    <property name="validationQuery" value="select 'x'" />
    <property name="timeBetweenEvictionRunsMillis" value="60000" />
    <property name="minEvictableIdleTimeMillis" value="600000" />
    <property name="testWhileIdle" value="true" />
    <property name="testOnBorrow" value="true" />
    <property name="testOnReturn" value="false" />
    <!-- Oracle下建议开启,MySQL下建议关闭 -->
    <property name="poolPreparedStatements" value="false" />
    <property name="connectionProperties" value="keepAlive=true" />
</bean>
gdsglgf commented 7 years ago

题主的问题解决了吗?

我也遇到类似的问题。如下是详细的异常信息:

org.springframework.transaction.CannotCreateTransactionException: Could not open JDBC Connection for transaction; nested exception is com.alibaba.druid.pool.DataSourceClosedException: dataSource already closed at Tue Jun 20 16:08:14 CST 2017
    at org.springframework.jdbc.datasource.DataSourceTransactionManager.doBegin(DataSourceTransactionManager.java:245)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:373)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:427)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:276)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:653)
    at com.nlp.service.WebService$$EnhancerBySpringCGLIB$$cd43518b.createWebURL(<generated>)
    at com.nlp.job.Standalone.parse(Standalone.java:105)
    at com.nlp.job.Consumer.run(ConcurrentJob.java:95)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
Caused by: com.alibaba.druid.pool.DataSourceClosedException: dataSource already closed at Tue Jun 20 16:08:14 CST 2017
    at com.alibaba.druid.pool.DruidDataSource.getConnectionInternal(DruidDataSource.java:1057)
    at com.alibaba.druid.pool.DruidDataSource.getConnectionDirect(DruidDataSource.java:960)
    at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:940)
    at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:930)
    at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:102)
    at org.springframework.jdbc.datasource.DataSourceTransactionManager.doBegin(DataSourceTransactionManager.java:204)
    ... 12 more
gdsglgf commented 7 years ago

问题已解决。原来是手动关闭了数据源。

ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
// some codes
ctx.close();   // 执行此行代码,会调用dataSource的destroy-method即close方法

解决方方法是删除或注释掉代码行ctx.close();

SummerXia93 commented 6 years ago

我也遇到了同样的问题,程序里面并没有任何手动开启或者关闭连接的代码。 使用的springboot+mybatis,今天启动的时候一直报这个错,希望能有大神帮忙解决 感激不尽

rency commented 6 years ago

我也是spring boot+mybatis,线程池执行批量任务也报这个错,大佬解决了么,怎么解决的

qq869610739 commented 5 years ago

我也是spring boot+mybatis 怎么解决的~!

MrIronMan commented 5 years ago

我最近也遇到了一样的问题 场景:在部署时报的错 原因:部署调用 actuator/shutdown 时的关闭顺序是有问题,应该先通知销毁 dubbo 或是之类的流量入口,再销毁bean,最后销毁DataSource就可以了 解决方案:监听 spring 的关机事件 ContextClosedEvent,关闭dubbo

sdd1989 commented 4 years ago

我最近也遇到了一样的问题 场景:在部署时报的错 原因:部署调用 actuator/shutdown 时的关闭顺序是有问题,应该先通知销毁 dubbo 或是之类的流量入口,再销毁bean,最后销毁DataSource就可以了 解决方案:监听 spring 的关机事件 ContextClosedEvent,关闭dubbo

我试了还是会有少量报错,也就是监听这个ContextClosedEvent事件还是保证不了一定比DataSource先销毁

sdd1989 commented 4 years ago

附上代码

public void onApplicationEvent(ContextClosedEvent event) {
        log.info("spring context destroy event:{}", event);
        try {
            ApplicationContext applicationContext = event.getApplicationContext();
            BeanDefinitionRegistry beanFactory = (BeanDefinitionRegistry) applicationContext.getAutowireCapableBeanFactory();
            Map<String, AbstractEMQConsumerService> map = applicationContext.getBeansOfType(AbstractEMQConsumerService.class);
            log.info("map:{}", map);
            if (map != null) {
                for (String beanName : map.keySet()) {
                    beanFactory.removeBeanDefinition(beanName);
                }
            }
        } catch (Throwable e) {
            log.error("spring context destroy error", e);
        }
    }
kiwi-field commented 3 years ago

多线程批量处理的时候只需要在service方法上加上@Transactional(rollbackFor = Exception.class)就行了,mybatis就不会每次执行完sql后closing sql session了

zhaojunliing commented 2 years ago

这个怎么重现呢

jeffchanjunwei commented 2 years ago

我最近也遇到了一样的问题 场景:在部署时报的错 原因:部署调用 actuator/shutdown 时的关闭顺序是有问题,应该先通知销毁 dubbo 或是之类的流量入口,再销毁bean,最后销毁DataSource就可以了 解决方案:监听 spring 的关机事件 ContextClosedEvent,关闭dubbo

我试了还是会有少量报错,也就是监听这个ContextClosedEvent事件还是保证不了一定比DataSource先销毁

这个少量报错后来有如何彻底解决的呢 @sdd1989

zhangl-w commented 10 months ago

多线程批量处理的时候只需要在service方法上加上@transactional(rollbackFor = Exception.class)就行了,mybatis就不会每次执行完sql后closing sql session了 还是报错啊