3

を使用するいくつかの Spring Batch (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" />

org.springframework.batch.core.launch.support.CommandLineJobRunnerはジョブを実行するために使用します:

java org.springframework.batch.core.launch.support.CommandLineJobRunner /com/XXX/job123/job123-context.xml job123 tenant.code=XXX -next 

すべてのジョブ (インクリメンターを使用する) はrootJobWithIncrementer親として持っています。

私はかなりの調査を行い、このエラーが発生した一部の人がトランザクション マネージャーの分離レベルを変更することに成功したことを発見しました。いくつかのレベルをいじり、最終的に にたどり着きましたREAD_COMMITED

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

私の理解に基づいて、このタイプのエラーは、同じジョブが複数のプロセスから同時に実行された場合にのみ発生するはずです。そのため、インクリメンターの競合が発生する可能性があります。この場合、そうではありませんが、エラーが表示されます。

この問題の原因について何か考えはありますか? 別の分離レベルを試す必要がありますか? 他の何か?

ありがとう!

hereに同様の質問がありますが、十分に文書化されていません(また、欠けており、回答もありません)。

4

1 に答える 1

1

JobInstanceAlreadyCompleteExceptionこれはロングショットかもしれませんが、あなたが説明したように散発的に唯一の症状が発生したため、それを理解するのに長い時間がかかりました.

私が使用していたデータベースは Oracle で、BATCH_JOB_SEQBATCH_JOB_EXECUTION_SEQが作成したデータベースはどちらもCACHE_SIZE10 でした。

これにより、JOB_INSTANCE_IDJOB_EXECUTION_IDが正しく順序付けられない場合がありました。Spring バッチは、最新JOB_INSTANCEのものはmax(JOB_INSTANCE_ID)( を参照org.springframework.batch.core.repository.dao.JdbcJobInstanceDao.FIND_LAST_JOBS_BY_NAME) のものであると想定します。私のシーケンスはときどき間違っていたので、この仮定が常に正しいとは限りませんでした。

シーケンスを に設定して修正しましたNO_CACHE

これが問題であるかどうかを判断する簡単な方法は、シーケンスが CACHE に設定されているかどうかを確認するか、新しい実行ごとにJOB_INSTANCE_IDJOB_EXECUTION_IDが常に昇順であることを確認することです。

于 2013-08-16T15:39:01.507 に答える