我最近在我的项目中出现了一个奇怪的问题,我似乎无法确定其来源,并且想知道那些精通Spring和Oracle的人是否可以对这个顽固的bug有所了解。
简而言之,当我开始工作时,它会在我的工作配置中执行第一步,然后每次输出以下内容。
2017-06-06 12:22:38.341 INFO 10776 --- [ask-scheduler-3] o.s.b.f.xml.XmlBeanDefinitionReader : Loading XML bean definitions from class path resource [org/springframework/jdbc/support/sql-error-codes.xml]
2017-06-06 12:22:38.360 INFO 10776 --- [ask-scheduler-3] o.s.jdbc.support.SQLErrorCodesFactory : SQLErrorCodes loaded: [DB2, Derby, H2, HSQL, Informix, MS-SQL, MySQL, Oracle, PostgreSQL, Sybase, Hana]
2017-06-06 12:22:38.412 ERROR 10776 --- [ask-scheduler-3] o.s.integration.handler.LoggingHandler : org.springframework.dao.CannotSerializeTransactionException: PreparedStatementCallback; SQL [INSERT INTO BATCH_JOB_EXECUTION_CONTEXT (SHORT_CONTEXT, SERIALIZED_CONTEXT, JOB_EXECUTION_ID) VALUES(?, ?, ?)]; ORA-08177: can't serialize access for this transaction
; nested exception is java.sql.SQLException: ORA-08177: can't serialize access for this transaction
at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:267)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:73)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:649)
at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:870)
at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:931)
at org.springframework.batch.core.repository.dao.JdbcExecutionContextDao.persistSerializedContext(JdbcExecutionContextDao.java:233)
at org.springframework.batch.core.repository.dao.JdbcExecutionContextDao.saveExecutionContext(JdbcExecutionContextDao.java:175)
at org.springframework.batch.core.repository.support.SimpleJobRepository.createJobExecution(SimpleJobRepository.java:146)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:333)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:282)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.batch.core.repository.support.AbstractJobRepositoryFactoryBean$1.invoke(AbstractJobRepositoryFactoryBean.java:172)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
at com.sun.proxy.$Proxy78.createJobExecution(Unknown Source)
at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:125)
at org.autodatacorp.dpt.importer.costimport.etl.scheduling.CostImportJobRunnable.launchCostImportJob(CostImportJobRunnable.java:64)
at org.autodatacorp.dpt.importer.costimport.etl.scheduling.CostImportJobRunnable.run(CostImportJobRunnable.java:48)
at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54)
at org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:81)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
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: java.sql.SQLException: ORA-08177: can't serialize access for this transaction
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:450)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:399)
at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:1059)
at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:522)
at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:257)
at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:587)
at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:225)
at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:53)
at oracle.jdbc.driver.T4CPreparedStatement.executeForRows(T4CPreparedStatement.java:943)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1150)
at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:4798)
at oracle.jdbc.driver.OraclePreparedStatement.executeUpdate(OraclePreparedStatement.java:4875)
at oracle.jdbc.driver.OraclePreparedStatementWrapper.executeUpdate(OraclePreparedStatementWrapper.java:1361)
at org.apache.commons.dbcp.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:105)
at org.apache.commons.dbcp.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:105)
at org.springframework.jdbc.core.JdbcTemplate$2.doInPreparedStatement(JdbcTemplate.java:877)
at org.springframework.jdbc.core.JdbcTemplate$2.doInPreparedStatement(JdbcTemplate.java:870)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:633)
... 32 more
这项工作将继续进行,但会不断反复出现这种错误。
我试图启用logback.xml来尝试获取有关正在发生的事情的更多信息,但似乎在执行时挂起作业进程。为应用程序启用调试模式会提供相同的错误,而无需额外的洞察力。我已经尝试使用Oracle的本地实例和远程,错误消息或频率没有区别。将oracle-batch.properties中的batch.isolationlevel设置为READ_COMMITED和ISOLATION_SERIALIZABLE不会解决问题。我已经验证我今天是我们亚马逊实例的唯一用户,否定了多个用户以某种方式访问数据库时发生冲突的可能性,并且已经验证我正在使用的代码确实构建没有错误。我还验证了在DatabaseConfiguration类中设置了@EnableTransaction注释。
正在使用最新版本的Spring Batch和Boot,而Oracle实例都使用Oracle 12c。其他应用程序可以使用相同的登录凭据进行正常连接(当我测试此应用程序时,它们没有连接到数据库)。当然,Spring批处理表确实存在于DB中,并且可以访问用于登录数据库的用户
简而言之,我已经没有可能性,因为这是什么原因以及如何让它变得快乐。有人遇到过这个问题,有什么建议吗?
编辑:根据要求,作业配置
@Bean
public Job sampleJob(@Qualifier("stepOne") Step stepOne,
@Qualifier("stepTwo") Step stepTwo,
@Qualifier("stepThree") Step stepThree,
@Qualifier("stepFour") Step stepFour,
@Qualifier("stepFive") Step stepFive,
@Qualifier("stepSix") Step stepSix,
@Qualifier("listener") CustomJobListener listener
) {
LOGGER.info("Starting Job");
return jobBuilderFactory.get("Importing Data")
.incrementer(new RunIdIncrementer())
.listener(listener)
.flow(stepOne)
.next(stepTwo)
.from(stepTwo).on(Constants.STEP_EXIT_STATUS_CONTINUE)
.to(stepThree)
.from(stepTwo).on(Constants.STEP_EXIT_STATUS_COMPLETED).end()
.from(stepThree)
.next(stepFour)
.from(stepFour).on(Constants.STEP_EXIT_STATUS_CONTINUE)
.to(transformingCostImportData)
.from(stepFour).on(Constants.STEP_EXIT_STATUS_COMPLETED).end()
.from(transformingCostImportData)
.next(stepFive)
.next(stepSix)
.next(stepTwo)
.build()
.build();
}