Spring Batch의 메타 테이블은 다음과 같이 6개의 테이블로 구성된다.
여기서 잡의 중복 실행을 방지해주는 테이블은 BATCH_JOB_INSTANCE인데 이 테이블은 Job Parameter에 따라 생성되는 테이블이다.
이때 Job Parameter는 Spring Batch가 실행될 때 외부에서 받을 수 있는 파라미터다. 예를 들어 특정 날짜를 Job Parameter로 넘기면 Spring Batch에서는 해당 날짜 데이터로 조회/가공/입력 등의 작업을 할 수 있다.
CREATE TABLE BATCH_JOB_INSTANCE (
JOB_INSTANCE_ID BIGINT NOT NULL PRIMARY KEY,
VERSION BIGINT,
JOB_NAME VARCHAR(100) NOT NULL,
JOB_KEY VARCHAR(32) NOT NULL,
CONSTRAINT JOB_INST_UN UNIQUE (JOB_NAME, JOB_KEY)
) ENGINE=InnoDB;
JOB_NAME과 JOB_KEY 컬럼은 유니크 제약 조건을 가지며 이를 통해 동일한 작업 이름과 파라미터 조합으로는 새로운 작업 인스턴스가 생성되지 않아 중복 실행이 방지된다.
즉, 같은 Batch Job이라도 Job Parameter가 다르면 BATCH_JOB_INSTANCE에 저장되며, Job Parameter가 같으면 저장되지 않고 JobInstanceAlreadyCompleteException를 터트리게 된다.
다음과 같이 현재 시간을 파라미터로 작업을 실행시킬 때 시간을 분 단위로 받는다면 매 요청마다 초 단위 차이가 나지만 중복 실행 방지에 의해 실행이 되지 않게 된다.
@GetMapping("/run-job")
public void runJob(@RequestParam("jobName") String jobName) throws Exception {
Job job = jobRegistry.getJob(jobName);
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd-hh-mm");
String date = dateFormat.format(new Date());
JobParameters jobParameters = new JobParametersBuilder()
.addString("date", date)
.toJobParameters();
jobLauncher.run(job, jobParameters);
}
Spring Batch에서는 동일한 파라미터로 작업을 재실행하고자 할 때 RunIdIncrementer를 사용할 수 있다. 이는 내부적으로 run.id라는 파라미터를 자동으로 증가시켜 매 실행마다 고유한 파라미터를 생성한다.
@Bean
public Job paymentJob(JobRepository jobRepository, Step paymentStep) {
return new JobBuilder(JOB_NAME, jobRepository)
.start(paymentStep)
.incrementer(new RunIdIncrementer())
.build();
}
하지만 RunIdIncrementer를 설정했더라도, 작업 실행 시 명시적으로 새로운 파라미터를 제공하지 않거나, 이전 실행 기록이 없는 경우 run.id가 생성되지 않을 수 있다. 따라서 JobLauncher를 통해 작업을 실행시킬 때 JobParametersBuilder의 getNextJobParameters 옵션을 통해 이전 실행 기록을 조회하여 새로운 파라미터를 생성할 수 있다. 그러면 내부적으로 JobParametersIncrementer을 이용해 자동으로 run.id 값을 설정해준다.
JobParameters jobParameters = new JobParametersBuilder(jobExplorer)
.getNextJobParameters(job)
.addString("date", date)
.toJobParameters();
jobLauncher.run(job, jobParameters);
1분 내에 연속해서 잡을 실행시켜보면 동일한 시간의 파라미터인데도 독립적으로 잡 인스턴스가 생성된 것을 볼 수 있다.

