【问题标题】:Spring Batch Illegal state (only happens > on a race condition): job execution already runningSpring Batch 非法状态(仅在竞争条件下发生):作业执行已在运行
【发布时间】:2019-01-09 04:43:27
【问题描述】:

在我的 Spring Batch 应用程序中,我使用 PostgreSQL 作为作业存储库并使用以下登录名来重新启动未完成的作业:

try {
    jobRegistry.register(new ReferenceJobFactory(documetPipelineJob));

    List<String> jobs = jobExplorer.getJobNames();
    for (String job : jobs) {

    Set<JobExecution> jobExecutions = jobExplorer.findRunningJobExecutions(job);

    for (JobExecution jobExecution : jobExecutions) {

        jobExecution.setStatus(BatchStatus.STOPPED);
        jobExecution.setEndTime(new Date());
        jobRepository.update(jobExecution);

        Long jobExecutionId = jobExecution.getId();
        jobOperator.restart(jobExecutionId);
    }
    }
} catch (Exception e) {
    LOGGER.error(e.getMessage(), e);
}

但此逻辑失败并出现以下异常:

2018-08-01 14:33:21.777 错误 32306 --- [主要] c.v.p.d.service.batch.BatchServiceImpl :非法状态(仅发生 在竞争条件下):作业执行已经运行 名称=documetPipelineJob 和参数=

这里可能有什么问题以及如何解决它?

更新

看起来jobRepository.update(jobExecution); 没有提交对数据库的更改。如何正确提交对数据库的更改?顺便说一句 - 这个逻辑适用于 H2 内存数据库。

【问题讨论】:

    标签: spring spring-boot spring-batch


    【解决方案1】:

    为了解决这个问题我加了incrementer(new RunIdIncrementer()):

    jobBuilderFactory.get("documetPipelineJob")
            .incrementer(new RunIdIncrementer())
            .start(initStep)
    

    我还扩展了重启逻辑以停止运行步骤:

    try {
        jobRegistry.register(new ReferenceJobFactory(documetPipelineJob));
    
        List<String> jobs = jobExplorer.getJobNames();
        for (String job : jobs) {
    
        Set<JobExecution> jobExecutions = jobExplorer.findRunningJobExecutions(job);
    
        for (JobExecution jobExecution : jobExecutions) {
    
            Collection<StepExecution> stepExecutions = jobExecution.getStepExecutions();
            for (StepExecution stepExecution : stepExecutions) {
            BatchStatus status = stepExecution.getStatus();
            if (status.isRunning() || status == BatchStatus.STOPPING) {
                stepExecution.setStatus(BatchStatus.STOPPED);
                stepExecution.setEndTime(new Date());
                jobRepository.update(stepExecution);
            }
            }
    
            jobExecution.setStatus(BatchStatus.STOPPED);
            jobExecution.setEndTime(new Date());
            jobRepository.update(jobExecution);
    
            Long jobExecutionId = jobExecution.getId();
    
            jobOperator.restart(jobExecutionId);
        }
        }
    } catch (Exception e) {
        LOGGER.error(e.getMessage(), e);
    }
    

    然后,我遇到了下面文章中描述的问题:Serialize Transaction Issue我同时运行了几个批处理作业。

    我通过将JobRepository 配置为ISOLATION_READ_UNCOMMITTED 来修复它:

    @Override
    protected JobRepository createJobRepository() throws Exception {
        JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
        factory.setDataSource(dataSource);
        factory.setTransactionManager(transactionManager);
        factory.setIsolationLevelForCreate("ISOLATION_READ_UNCOMMITTED");
        factory.afterPropertiesSet();
        return factory.getObject();
    }
    

    【讨论】:

      猜你喜欢
      • 2023-03-30
      • 2017-04-29
      • 2020-11-23
      • 2014-12-10
      • 1970-01-01
      • 2020-09-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多