spring batch job 중복 실행 오류 - JobInstance already exists and is not restartable

러블리소피·2024년 12월 31일

JobInstance already exists and is not restartable 오류 원인과 해결방법

원인

1. 중복된 Job Parameters

  • Spring Batch는 JobInstance를 생성할 때, Job Name과 Job Parameters의 조합을 사용하여 고유하게 식별합니다.
  • 동일한 Job Name과 동일한 Job Parameters로 실행 요청을 하면 이미 존재하는 JobInstance를 재사용하려고 시도합니다.
  • 그러나 JobInstance가 이미 실행되고 완료된 상태라면, 기본적으로 재실행이 불가능합니다.

2. Job 재시작 설정 문제

Job이 중단되거나 실패했을 경우, 이를 재시작하려면 해당 JobInstance가 restartable 상태여야 합니다.
그렇지 않을 경우 위와 같은 오류가 발생합니다.

해결 방법

1. Job Parameters 변경

  • 매번 고유한 Job Parameters를 추가하여 새 JobInstance를 생성하도록 만듭니다.
    java
JobParameters jobParameters = new JobParametersBuilder()
    .addString("uniqueKey", UUID.randomUUID().toString()) // 고유한 키 추가
    .addDate("currentTime", new Date())                  // 현재 시간 추가
    .toJobParameters();

jobLauncher.run(job, jobParameters);

2. Job 재시작 설정 확인

  • @EnableBatchProcessing과 Job 설정에서 restartable 속성을 확인하세요.
  • Job이 재시작 가능하도록 설정되어 있어야 합니다.
@Bean
public Job exampleJob(JobBuilderFactory jobBuilderFactory, Step step) {
    return jobBuilderFactory.get("exampleJob")
        .start(step)
        .preventRestart(false) // 재시작 가능하도록 설정
        .build();
}

3. 실패한 JobInstance 확인 및 재시작

  • 데이터베이스에서 기존의 JobInstance를 확인하고 실패한 경우 재시작할 수 있는지 확인합니다.
SELECT * FROM BATCH_JOB_INSTANCE;
SELECT * FROM BATCH_JOB_EXECUTION WHERE JOB_INSTANCE_ID = <ID>;
  • 재시작 가능하다면 JobExplorer를 사용해 해당 JobInstance를 재실행할 수 있습니다.

4. 기존 JobInstance 삭제

  • 테스트 환경에서만 추천되는 방법입니다.
  • 기존 JobInstance를 강제로 삭제하여 새로운 JobInstance를 생성할 수 있습니다.
DELETE FROM BATCH_JOB_EXECUTION WHERE JOB_INSTANCE_ID = <ID>;
DELETE FROM BATCH_JOB_INSTANCE WHERE JOB_INSTANCE_ID = <ID>;

5. 조건부 실행으로 중복 방지

  • 동일한 JobParameters로 실행될 가능성이 있다면, 실행 전에 기존 JobInstance의 상태를 확인하여 중복 실행을 방지합니다.
JobInstance lastInstance = jobExplorer.getJobInstance("exampleJob", jobParameters);
if (lastInstance != null) {
    System.out.println("Job already exists. Skipping execution.");
} else {
    jobLauncher.run(job, jobParameters);
}

6. 매 실행마다 고유한 JobParameters 생성

  • RunIdIncrementer는 run.id라는 기본 파라미터를 추가하거나, 기존에 존재하면 값을 1 증가시킵니다.
  • 이를 통해 동일한 Job Name으로 실행하더라도 항상 새로운 JobParameters가 생성되므로 JobInstance 충돌을 방지할 수 있습니다.
@Bean
public Job exampleJob(JobBuilderFactory jobBuilderFactory, Step step) {
    return jobBuilderFactory.get("exampleJob")
        .incrementer(new RunIdIncrementer()) // 매 실행마다 고유한 JobParameters 생성
        .start(step)
        .build();
}

운영 환경 사용 시 신중

  • RunIdIncrementer는 매번 새로운 JobInstance를 생성하므로, 동일한 파라미터로 Job을 재시작해야 할 경우 적합하지 않습니다.
  • 실패한 Job의 재실행이 필요할 경우에는 RunIdIncrementer 대신 고유한 Job Parameters를 명시적으로 관리하는 것이 더 좋습니다.

run.id 파라미터 사용 의존성

  • 다른 비즈니스 로직에서 run.id를 참조하지 않도록 주의하세요. 이는 Spring Batch 내부에서만 사용되는 부가적인 값입니다.

추천 접근법

  • 운영 환경: 항상 고유한 Job Parameters를 제공하거나 실패한 Job을 정확히 재시작할 수 있도록 관리합니다.
  • 테스트 환경: 기존 데이터를 삭제하거나 preventRestart(false)로 설정하여 테스트를 원활히 진행합니다.
profile
발전하는 개발자가 되고싶어요

0개의 댓글