Spring batch 弹簧批';RunIdIncrementer';不生成下一个值

Spring batch 弹簧批';RunIdIncrementer';不生成下一个值,spring-batch,Spring Batch,我有几个SpringBatch(2.1.9.RELEASE)作业在生产环境中运行,它们使用org.springframework.Batch.core.launch.support.RunIdIncrementer 偶尔,我会出现以下错误: org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException: A job instance already exists and is complete for

我有几个SpringBatch(2.1.9.RELEASE)作业在生产环境中运行,它们使用
org.springframework.Batch.core.launch.support.RunIdIncrementer

偶尔,我会出现以下错误:

org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException: A job instance already exists and is complete for parameters={run.id=23, tenant.code=XXX}.  If you want to run this job again, change the parameters.
    at org.springframework.batch.core.repository.support.SimpleJobRepository.createJobExecution(SimpleJobRepository.java:122) ~[spring-batch-core-2.1.9.RELEASE.jar:na]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.6.0_39]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) ~[na:1.6.0_39]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) ~[na:1.6.0_39]
    at java.lang.reflect.Method.invoke(Method.java:597) ~[na:1.6.0_39]
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:318) ~[spring-aop-3.1.1.RELEASE.jar:3.1.1.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183) ~[spring-aop-3.1.1.RELEASE.jar:3.1.1.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150) ~[spring-aop-3.1.1.RELEASE.jar:3.1.1.RELEASE]
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110) ~[spring-tx-3.1.1.RELEASE.jar:3.1.1.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) ~[spring-aop-3.1.1.RELEASE.jar:3.1.1.RELEASE]
    at org.springframework.batch.core.repository.support.AbstractJobRepositoryFactoryBean$1.invoke(AbstractJobRepositoryFactoryBean.java:168) ~[spring-batch-core-2.1.9.RELEASE.jar:na]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) ~[spring-aop-3.1.1.RELEASE.jar:3.1.1.RELEASE]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202) ~[spring-aop-3.1.1.RELEASE.jar:3.1.1.RELEASE]
    at sun.proxy.$Proxy64.createJobExecution(Unknown Source) ~[na:na]
    at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:111) ~[spring-batch-core-2.1.9.RELEASE.jar:na]
    at org.springframework.batch.core.launch.support.CommandLineJobRunner.start(CommandLineJobRunner.java:349) [spring-batch-core-2.1.9.RELEASE.jar:na]
    at org.springframework.batch.core.launch.support.CommandLineJobRunner.main(CommandLineJobRunner.java:574) [spring-batch-core-2.1.9.RELEASE.jar:na]
    at (omitted for brevity)
来自各种XML上下文的采样:

<bean
    id="jobParametersIncrementer"
    class="org.springframework.batch.core.launch.support.RunIdIncrementer" />

<batch:job id="rootJob"
    abstract="true"
    restartable="true">
    <batch:validator>
        <bean class="org.springframework.batch.core.job.DefaultJobParametersValidator">
            <property name="requiredKeys" value="tenant.code"/>
        </bean>
    </batch:validator>
</batch:job>

<batch:job id="rootJobWithIncrementer"
    abstract="true"
    parent="rootJob"
    incrementer="jobParametersIncrementer" />
所有作业(使用递增器)都将
rootJobWithIncrementer
作为父作业

我做了大量的研究,发现一些犯了这个错误的人成功地改变了事务管理器的隔离级别。我摆弄了好几个关卡,终于找到了
READ\u committed

<batch:job-repository
    id="jobRepository"
    data-source="oracle_hmp"
    transaction-manager="dataSourceTransactionManager"
    isolation-level-for-create="READ_COMMITTED"/>

根据我的理解,只有在同一个作业从多个进程同时执行的情况下,才会发生这种类型的错误——因此可能存在对递增器的争用。在本例中,这是而不是的情况,但是我们看到了错误

有没有关于是什么导致了这个问题的想法?我应该尝试不同的隔离级别吗?还有别的吗

谢谢


有一个类似的问题,但它没有很好的文档记录(也缺少答案)。

这可能是一个很长的机会,但我花了很长时间才弄清楚,因为唯一的症状是偶尔出现您描述的
JobInstanceAlreadyCompleteException
,所以我想我建议这样做

我使用的数据库是Oracle,我创建的
BATCH\u JOB\u SEQ
BATCH\u JOB\u EXECUTION\u SEQ
缓存大小都是10

这有时会导致
JOB\u实例ID
JOB\u执行ID
顺序不正确。SpringBatch假设最近的
JOB\u实例是具有
max(JOB\u实例ID)
的实例(请参见
org.springframework.batch.core.repository.dao.JdbcJobInstanceDao.FIND\u LAST\u JOBS\u BY\u NAME
)。由于我的序列有时被抛出,这个假设并不总是成立的

我通过将序列设置为
NO\u CACHE
来修复它


判断这是否是您的问题的一个简单方法是检查您的序列是否设置为缓存,和/或确保您的
JOB\u实例\u ID
JOB\u执行\u ID
始终随每次新运行而上升。

您是否尝试过上述默认隔离级别?你能升级到2.2.1.RELEASE吗(但是changelog不包含关于incrementer的问题)?我尝试了几种隔离级别,包括default-SERIALIZABLE。我将尝试升级-我们的代码库目前正在使用Spring3.1.X,但根据项目POM,SpringBatch 2.2.1需要Spring3.2.X-我有点担心升级,但我会尝试一下。谢谢感谢@FGreg在序列中添加“增量1”对我来说已经足够了。我错了,没有缓存是必要的。
<batch:job-repository
    id="jobRepository"
    data-source="oracle_hmp"
    transaction-manager="dataSourceTransactionManager"
    isolation-level-for-create="READ_COMMITTED"/>