偶发:java.sql.SQLException: ORA-00028: your session has been killed

最近一段时间,新项目上线。其中一个项目是关于Kafka消息消费的处理工程。

日志中,很低概率地会发生下面的错误:

	org.springframework.jdbc.support.MetaDataAccessException: Error while extracting DatabaseMetaData; nested exception is java.sql.SQLException: Closed Connection
	at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:342) ~[spring-jdbc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
	at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:366) ~[spring-jdbc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
	at org.springframework.jdbc.support.SQLErrorCodesFactory.getErrorCodes(SQLErrorCodesFactory.java:212) [spring-jdbc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
	at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.setDataSource(SQLErrorCodeSQLExceptionTranslator.java:134) [spring-jdbc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
	at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.<init>(SQLErrorCodeSQLExceptionTranslator.java:97) [spring-jdbc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
	at org.mybatis.spring.MyBatisExceptionTranslator.initExceptionTranslator(MyBatisExceptionTranslator.java:89) [mybatis-spring-1.3.0.jar:1.3.0]
	at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:74) [mybatis-spring-1.3.0.jar:1.3.0]
	at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:447) [mybatis-spring-1.3.0.jar:1.3.0]
	at com.sun.proxy.$Proxy79.update(Unknown Source) [?:?]
	at org.mybatis.spring.SqlSessionTemplate.update(SqlSessionTemplate.java:295) [mybatis-spring-1.3.0.jar:1.3.0]
	at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:59) [mybatis-3.4.0.jar:3.4.0]
	at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:53) [mybatis-3.4.0.jar:3.4.0]
	at com.sun.proxy.$Proxy83.modifyOrderStatusByOrderId(Unknown Source) [?:?]
	at sun.reflect.GeneratedMethodAccessor700.invoke(Unknown Source) ~[?:?]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_45]
	at java.lang.reflect.Method.invoke(Method.java:497) ~[?:1.8.0_45]
	at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:333) [spring-aop-4.3.13.RELEASE.jar:4.3.13.RELEASE]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190) [spring-aop-4.3.13.RELEASE.jar:4.3.13.RELEASE]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) [spring-aop-4.3.13.RELEASE.jar:4.3.13.RELEASE]
	at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136) [spring-tx-4.3.13.RELEASE.jar:?]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) [spring-aop-4.3.13.RELEASE.jar:4.3.13.RELEASE]
	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213) [spring-aop-4.3.13.RELEASE.jar:4.3.13.RELEASE]
	at com.sun.proxy.$Proxy84.modifyOrderStatusByOrderId(Unknown Source) [?:?]
	at com.xxx.retailorder.syncpostmall.service.impl.PaymentCompServiceImpl.paymentDataSync(PaymentCompServiceImpl.java:101) [PaymentCompServiceImpl.class:?]
	at com.xxx.retailorder.syncpostmall.service.impl.PaymentCompServiceImpl$$FastClassBySpringCGLIB$$2b9f2446.invoke(<generated>) [PaymentCompServiceImpl.class:?]
	at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) [spring-core-4.3.13.RELEASE.jar:?]
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:738) [spring-aop-4.3.13.RELEASE.jar:4.3.13.RELEASE]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) [spring-aop-4.3.13.RELEASE.jar:4.3.13.RELEASE]
	at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99) [spring-tx-4.3.13.RELEASE.jar:4.3.13.RELEASE]
	at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:282) [spring-tx-4.3.13.RELEASE.jar:4.3.13.RELEASE]
	at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96) [spring-tx-4.3.13.RELEASE.jar:4.3.13.RELEASE]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) [spring-aop-4.3.13.RELEASE.jar:4.3.13.RELEASE]
	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:673) [spring-aop-4.3.13.RELEASE.jar:4.3.13.RELEASE]
	at com.xxx.retailorder.syncpostmall.service.impl.PaymentCompServiceImpl$$EnhancerBySpringCGLIB$$74a32680.paymentDataSync(<generated>) [PaymentCompServiceImpl.class:?]
	at sun.reflect.GeneratedMethodAccessor699.invoke(Unknown Source) ~[?:?]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_45]
	at java.lang.reflect.Method.invoke(Method.java:497) ~[?:1.8.0_45]
	at com.xxx.retailorder.syncpostmall.multithread.MessageHandThread.run(MessageHandThread.java:85) [MessageHandThread.class:?]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [?:1.8.0_45]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [?:1.8.0_45]
	at java.lang.Thread.run(Thread.java:745) [?:1.8.0_45]
Caused by: java.sql.SQLException: Closed Connection
	at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:112) ~[ojdbc14-10.2.0.2.0.jar:Oracle JDBC Driver version - "10.2.0.3.0"]
	at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:146) ~[ojdbc14-10.2.0.2.0.jar:Oracle JDBC Driver version - "10.2.0.3.0"]
	at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:208) ~[ojdbc14-10.2.0.2.0.jar:Oracle JDBC Driver version - "10.2.0.3.0"]
	at oracle.jdbc.driver.PhysicalConnection.getMetaData(PhysicalConnection.java:1578) ~[ojdbc14-10.2.0.2.0.jar:Oracle JDBC Driver version - "10.2.0.3.0"]
	at org.apache.commons.dbcp.DelegatingConnection.getMetaData(DelegatingConnection.java:345) ~[commons-dbcp-1.4.jar:1.4]
	at org.apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper.getMetaData(PoolingDataSource.java:245) ~[commons-dbcp-1.4.jar:1.4]
	at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:331) ~[spring-jdbc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
	... 40 more
	2018-08-29 09:02:49 739[ERROR][pool-2-thread-2][TransactionInterceptor:]:Application exception overridden by rollback exception
	; nested exception is java.sql.SQLException: ORA-00028: your session has been killed
	2018-08-29 09:02:49 748[ERROR][pool-2-thread-2][MessageHandThread:]:serviceMethod.invoke encountered an exception

日志告诉我们:当前某个业务被分配到的数据库链接被关闭了。

关键组件版本及配置是这样的。

    <!-- 数据源公用配置 -->
    <bean id="parentDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name= "testWhileIdle" value="true" />
        <property name= "testOnBorrow" value="false" />
        <property name= "testOnReturn" value="false" />
        <property name= "timeBetweenEvictionRunsMillis" value="30000" />
    </bean>
    <!-- 数据连接池 -->
    <bean id="dataSource" parent="parentDataSource" primary="true">
        <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
        <property name="url" value="${jdbc.postmall-master.url}" />
        <property name="username" value="${jdbc.postmall-master.username}" />
        <property name="password" value="${jdbc.postmall-master.password}" />
        <property name="initialSize" value="${jdbc.postmall-master.initialSize}" />
        <property name="maxActive" value="${jdbc.postmall-master.maxActive}" />
        <property name="maxIdle" value="${jdbc.postmall-master.maxIdle}" />
        <property name="minIdle" value="${jdbc.postmall-master.minIdle}" />
        <property name="validationQuery" value="${jdbc.postmall-master.validationQuery}" />
    </bean>
 
   <!-- spring事务管理器 -->
    <bean id="transactionManager"  class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />  
    </bean>
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource" /> 
        <property name="configLocation" value="classpath:mybatis-configuration.xml"></property>
        <property name="mapperLocations" value="classpath:mybatis/*.xml"/>
    </bean>
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/> 
        <property name="basePackage" value="com.xxx.retailorder.*.dao" />
    </bean>
    <tx:annotation-driven transaction-manager="transactionManager" />
    <!-- SqlSessionTemplate sqlSession模板 -->
    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
        <constructor-arg index="0" ref="sqlSessionFactory" />
    </bean>
    <!-- 配置使Spring采用CGLIB代理 -->
    <aop:aspectj-autoproxy expose-proxy="true" proxy-target-class="true" />
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.1.1</version>
        </dependency>
        <dependency>
            <groupId>commons-dbcp</groupId>
            <artifactId>commons-dbcp</artifactId>
            <version>1.4</version>
        </dependency>
        <dependency>
            <groupId>com.oracle</groupId>
            <artifactId>ojdbc14</artifactId>
            <version>10.2.0.2.0</version>
        </dependency>

查了很多资料,同事帮我找到这个资料:https://stackoverflow.com/questions/7350680/dbcp-returns-closed-connections

On DBCP, your best bet is to validate connections before returning by a testOnBorrow=true and a validationQuery setting, e.g. SELECT 1.

还有人说DBCP在高并发时不太好。所以,换成了Duird,并且升级了Spring-Mybatis包,将连接池的配置testOnBorrow改成了true。

接着就改成了下面的配置。

    <!-- 数据源公用配置 -->
    <bean id="parentDataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
        <property name= "testWhileIdle" value="true" />
        <property name= "testOnBorrow" value="true" />
        <property name= "testOnReturn" value="false" />
        <property name= "timeBetweenEvictionRunsMillis" value="30000" />
        <property name= "minEvictableIdleTimeMillis" value="300000" />
    </bean>
... ...
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.1</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.10</version>
        </dependency>
        <dependency>
            <groupId>com.oracle</groupId>
            <artifactId>ojdbc14</artifactId>
            <version>10.2.0.2.0</version>
        </dependency>

改成上面发布生产后,一天内发生了两次下面的错误。

	2018-08-30 09:08:30 087[ERROR][Druid-ConnectionPool-Destroy-351064647][JdbcUtils:]:close connection error
	java.sql.SQLException: ORA-00028: your session has been killed
		at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:112) ~[ojdbc14-10.2.0.2.0.jar:Oracle JDBC Driver version - "10.2.0.3.0"]
	at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:331) ~[ojdbc14-10.2.0.2.0.jar:Oracle JDBC Driver version - "10.2.0.3.0"]
	at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:283) ~[ojdbc14-10.2.0.2.0.jar:Oracle JDBC Driver version - "10.2.0.3.0"]
	at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:278) ~[ojdbc14-10.2.0.2.0.jar:Oracle JDBC Driver version - "10.2.0.3.0"]
	at oracle.jdbc.driver.T4C7Ocommoncall.receive(T4C7Ocommoncall.java:141) ~[ojdbc14-10.2.0.2.0.jar:Oracle JDBC Driver version - "10.2.0.3.0"]
	at oracle.jdbc.driver.T4CConnection.logoff(T4CConnection.java:465) ~[ojdbc14-10.2.0.2.0.jar:Oracle JDBC Driver version - "10.2.0.3.0"]
	at oracle.jdbc.driver.PhysicalConnection.close(PhysicalConnection.java:1203) ~[ojdbc14-10.2.0.2.0.jar:Oracle JDBC Driver version - "10.2.0.3.0"]
	at com.alibaba.druid.util.JdbcUtils.close(JdbcUtils.java:73) [druid-1.1.10.jar:?]
	at com.alibaba.druid.pool.DruidDataSource.shrink(DruidDataSource.java:2797) [druid-1.1.10.jar:?]
	at com.alibaba.druid.pool.DruidDataSource$DestroyTask.run(DruidDataSource.java:2562) [druid-1.1.10.jar:?]
	at com.alibaba.druid.pool.DruidDataSource$DestroyConnectionThread.run(DruidDataSource.java:2549) [druid-1.1.10.jar:?]

很显然,跟前回版本的错误不一样了。这次是线程池回收线程中发现了被关闭链接的sqlsession。

直到现在,还是没有找到根本原因。

下个版本,准备将ojdbc14从10.2.0.2升级到10.2.0.4试试。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值