LoginSignup
3
1

More than 5 years have passed since last update.

Spring BatchをOracleで連続Job実行するとORA-08177

Posted at

現象

以下のコードのように、ほとんど間を空けずにjobをlaunchする。

ExecutorService s = Executors.newFixedThreadPool(2);

long time1 = new Date().getTime();
long time2 = time1 + 111111000;
s.execute(() -> doBatch(time1));
s.execute(() -> doBatch(time2));

void doBatch(long t) {
    Map<String, JobParameter> p = new HashMap<String, JobParameter>();
    p.put("a", new JobParameter(new Date(t)));
    JobParameters jobParameters = new JobParameters(p);
    l.run(job, jobParameters)

これを実行すると、以下のようなエラーになる。

Exception in thread "pool-1-thread-1" org.springframework.dao.CannotSerializeTransactionException: PreparedStatementCallback; SQL [INSERT into BATCH_JOB_INSTANCE(JOB_INSTANCE_ID, JOB_NAME, JOB_KEY, VERSION) values (?, ?, ?, ?)]; ORA-08177: このトランザクションのアクセスをシリアル化できません
; nested exception is java.sql.SQLException: ORA-08177: このトランザクションのアクセスをシリアル化できません

    at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:270)
    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72)
    at org.springframework.jdbc.core.JdbcTemplate.translateException(JdbcTemplate.java:1444)
    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:632)

これの原因は Spring Batch ORA-08177: can't serialize access for this transaction when running single job, SERIALIZED isolation level とかに書いてある。

解決策

というわけでIsolationLevelREAD_UNCOMMITTEDに変えてしまえばよい。

@Configuration
@EnableBatchProcessing
public class BatchConfiguration1 extends DefaultBatchConfigurer {
    @Autowired
    DataSource configDataSource;

    @Autowired
    PlatformTransactionManager configTxManager;

    @Override
    protected JobRepository createJobRepository() throws Exception {
        JobRepositoryFactoryBean factoryBean = new JobRepositoryFactoryBean();
        factoryBean.setDataSource(configDataSource);
        factoryBean.setTransactionManager(configTxManager);
        factoryBean.setIsolationLevelForCreate("ISOLATION_READ_COMMITTED");
        factoryBean.setTablePrefix("BATCH_");
        try {
            factoryBean.afterPropertiesSet();
            return factoryBean.getObject();
        } catch (Exception e) {
            throw new BatchConfigurationException(e);
        }
    }
3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1