我正在使用带有Spring Boot的Spring Batch 3并实现了一个简单的作业步骤,该步骤将标准JpaPagingItemReader配置为reader。我正在使用SimpleAsynTaskProcessor并行执行此步骤中的每个块。
问题是我收到(应用程序每万条记录一次)LockAquisition Exceptions:
javax.persistence.PersistenceException: org.hibernate.exception.LockAcquisitionException: could not extract ResultSet
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1763)
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1677)
at org.hibernate.jpa.internal.QueryImpl.getResultList(QueryImpl.java:458)
at org.springframework.batch.item.database.JpaPagingItemReader.doReadPage(JpaPagingItemReader.java:219)
at org.springframework.batch.item.database.AbstractPagingItemReader.doRead(AbstractPagingItemReader.java:108)
at org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader.read(AbstractItemCountingItemStreamItemReader.java:88)
at org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader$$FastClassBySpringCGLIB$$ebb633d0.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:708)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:133)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:121)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:644)
at org.springframework.batch.item.database.JpaPagingItemReader$$EnhancerBySpringCGLIB$$3a5ef58b.read(<generated>)
at org.springframework.batch.core.step.item.SimpleChunkProvider.doRead(SimpleChunkProvider.java:91)
at org.springframework.batch.core.step.item.FaultTolerantChunkProvider.read(FaultTolerantChunkProvider.java:87)
at org.springframework.batch.core.step.item.SimpleChunkProvider$1.doInIteration(SimpleChunkProvider.java:114)
at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:368)
at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:215)
at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:144)
at org.springframework.batch.core.step.item.SimpleChunkProvider.provide(SimpleChunkProvider.java:108)
at org.springframework.batch.core.step.item.ChunkOrientedTasklet.execute(ChunkOrientedTasklet.java:69)
at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:406)
at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:330)
at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:133)
at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:271)
at org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:77)
at org.springframework.batch.repeat.support.TaskExecutorRepeatTemplate$ExecutingRunnable.run(TaskExecutorRepeatTemplate.java:262)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.hibernate.exception.LockAcquisitionException: could not extract ResultSet
at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:140)
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:49)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:126)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:112)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:89)
at org.hibernate.loader.Loader.getResultSet(Loader.java:2065)
at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1862)
at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1838)
at org.hibernate.loader.Loader.doQuery(Loader.java:909)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:354)
at org.hibernate.loader.Loader.doList(Loader.java:2553)
at org.hibernate.loader.Loader.doList(Loader.java:2539)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2369)
at org.hibernate.loader.Loader.list(Loader.java:2364)
at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:496)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:387)
at org.hibernate.engine.query.spi.HQLQueryPlan.performList(HQLQueryPlan.java:231)
at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1264)
at org.hibernate.internal.QueryImpl.list(QueryImpl.java:103)
at org.hibernate.jpa.internal.QueryImpl.list(QueryImpl.java:573)
at org.hibernate.jpa.internal.QueryImpl.getResultList(QueryImpl.java:449)
... 27 common frames omitted
Caused by: java.sql.SQLException: Die Transaktion (Prozess-ID 67) befand sich auf Sperre Ressourcen aufgrund eines anderen Prozesses in einer Deadlocksituation und wurde als Deadlockopfer ausgewählt. Führen Sie die Transaktion erneut aus.
at net.sourceforge.jtds.jdbc.SQLDiagnostic.addDiagnostic(SQLDiagnostic.java:372)
at net.sourceforge.jtds.jdbc.TdsCore.tdsErrorToken(TdsCore.java:2988)
at net.sourceforge.jtds.jdbc.TdsCore.nextToken(TdsCore.java:2421)
at net.sourceforge.jtds.jdbc.TdsCore.getNextRow(TdsCore.java:809)
at net.sourceforge.jtds.jdbc.MSCursorResultSet.processOutput(MSCursorResultSet.java:956)
at net.sourceforge.jtds.jdbc.MSCursorResultSet.cursorCreate(MSCursorResultSet.java:541)
at net.sourceforge.jtds.jdbc.MSCursorResultSet.<init>(MSCursorResultSet.java:154)
at net.sourceforge.jtds.jdbc.JtdsStatement.executeSQLQuery(JtdsStatement.java:452)
at net.sourceforge.jtds.jdbc.JtdsPreparedStatement.executeQuery(JtdsPreparedStatement.java:1029)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:80)
... 43 common frames omitted
我的步骤和项目阅读器的定义如下:
/* when job parameter importType = FULL_IMPORT*/
@Bean(name="importIFAPFullStep")
public Step importIFAPFullStep(StepBuilderFactory stepBuilderFactory,
@Qualifier("importIFAPFullReader") ItemReader<Product> reader,
@Qualifier("importIFAPWriter") ItemWriter<Product> writer,
@Qualifier("importIFAPProcessor") ItemProcessor<Product, Product> processor) {
return stepBuilderFactory.get("importIFAPFullStep")
.<Product, Product> chunk(Integer.valueOf(env.getProperty("importIFAPFullStep.chunk.size")))
.faultTolerant()
.retryPolicy(new NeverRetryPolicy()) //cannot retry due to multi-threaded nature
.skipLimit(Integer.valueOf(env.getProperty("importIFAPFullStep.skip.limit")))
.skip(RuntimeException.class)
.listener(new ItemSkipListener())
.reader(reader)
.processor(processor)
.writer(writer)
.taskExecutor(new SimpleAsyncTaskExecutor("iifs")) //new ManagedExecutorService())
.throttleLimit(Integer.valueOf(env.getProperty("importIFAPFullStep.throttle.limit")))
.build();
}
/* Reader*/
@Bean(name="importIFAPFullReader", destroyMethod="")
@StepScope
public JpaPagingItemReader<Product> importIFAPFullReader() {
JpaPagingItemReader<Product> reader = new JpaPagingItemReader<Product>();
reader.setEntityManagerFactory(emFactoryBean.getObject());
reader.setTransacted(false);
reader.setPageSize(Integer.valueOf(env.getProperty("importIFAPFullReader.page.size")));
reader.setSaveState(false); //job not restartable due to multithreaded nature
reader.setQueryString("select new com.docmorris.pib.ifap.model.Product(p.id, p.pzn, p.clientId, p.version) from Product p order by p.pzn desc");
return reader;
}
我使用sqlserver 2012作为数据库实现。我假设这些异常不会发生,因为JpaPagingItemReader是安全的,我开箱即用。
我尝试了其他几个TaskExecutor实现(并尝试了很多其他的东西),但似乎没有任何工作。
有人能指出我正确的方向吗?这与sqlserver有关吗?
我在启动时看到过此警告,并且如果相关则会徘徊: o.s.b.a.batch.BasicBatchConfigurer:JPA不支持自定义隔离级别,因此在启动作业时可能无法进行锁定
我检查了源代码,看起来spring boot总是将隔离级别设置为ISOLATION_DEFAULT。但可能是这只是工作回购的隔离级别,我不确定:)
许多反馈意见!
此致
金