Spring Batch无法获取last_insert_id();嵌套异常是java.sql.SQLException:超出锁定等待超时;

时间:2015-12-05 17:02:14

标签: spring spring-batch last-insert-id

我在MySQL数据库上使用spring batch 3.0.5.RELEASE。 我有一份工作,从多个表中读取并处理记录并在完成后标记其状态。作业数据的设计方式使得同一作业的多个实例可以在不踩彼此脚趾的情况下运行..(它们有自己的数据集可以使用)

我有以下作业存储库配置。

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

当我运行此作业的多个实例时,我会在一段时间后得到以下异常。某些实例已成功完成,但某些实例因此异常而失败。

[12-04-2015 17:08:06,276] [Thread 39] ERROR org.springframework.batch.core.job.AbstractJob: Encountered fatal error executing job
org.springframework.batch.core.JobExecutionException: Flow execution ended unexpectedly
    at org.springframework.batch.core.job.flow.FlowJob.doExecute(FlowJob.java:140)
    at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:306)
    at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:135)
    at org.springframework.core.task.SimpleAsyncTaskExecutor$ConcurrencyThrottlingRunnable.run(SimpleAsyncTaskExecutor.java:251)
    at java.lang.Thread.run(Thread.java:745)
Caused by: org.springframework.batch.core.job.flow.FlowExecutionException: Ended flow=SuspendAccountFlow at state=SuspendAccountFlow.partitionAccountListStep with exception
    at org.springframework.batch.core.job.flow.support.SimpleFlow.resume(SimpleFlow.java:178)
    at org.springframework.batch.core.job.flow.support.SimpleFlow.start(SimpleFlow.java:144)
    at org.springframework.batch.core.job.flow.FlowJob.doExecute(FlowJob.java:134)
    ... 4 more
Caused by: org.springframework.dao.DataAccessResourceFailureException: Could not obtain last_insert_id(); nested exception is java.sql.SQLException: Lock wait timeout exceeded; try restarting transaction
    at org.springframework.jdbc.support.incrementer.MySQLMaxValueIncrementer.getNextKey(MySQLMaxValueIncrementer.java:118)
    at org.springframework.jdbc.support.incrementer.AbstractDataFieldMaxValueIncrementer.nextLongValue(AbstractDataFieldMaxValueIncrementer.java:128)
    at org.springframework.batch.core.repository.dao.JdbcStepExecutionDao.buildStepExecutionParameters(JdbcStepExecutionDao.java:187)
    at org.springframework.batch.core.repository.dao.JdbcStepExecutionDao.saveStepExecution(JdbcStepExecutionDao.java:118)
    at org.springframework.batch.core.repository.support.SimpleJobRepository.add(SimpleJobRepository.java:170)
    at sun.reflect.GeneratedMethodAccessor81.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:281)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
    at com.sun.proxy.$Proxy25.add(Unknown Source)
    at sun.reflect.GeneratedMethodAccessor81.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
    at org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$PassthruAdvice.invoke(SimpleBatchConfiguration.java:127)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
    at com.sun.proxy.$Proxy25.add(Unknown Source)
    at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:144)
    at org.springframework.batch.core.job.flow.JobFlowExecutor.executeStep(JobFlowExecutor.java:64)
    at org.springframework.batch.core.job.flow.support.state.StepState.handle(StepState.java:67)
    at org.springframework.batch.core.job.flow.support.SimpleFlow.resume(SimpleFlow.java:169)
    ... 6 more
Caused by: java.sql.SQLException: Lock wait timeout exceeded; try restarting transaction
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:998)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3847)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3783)
    at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2447)
    at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2594)
    at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2541)
    at com.mysql.jdbc.StatementImpl.executeUpdate(StatementImpl.java:1604)
    at com.mysql.jdbc.StatementImpl.executeUpdate(StatementImpl.java:1535)
    at org.apache.commons.dbcp.DelegatingStatement.executeUpdate(DelegatingStatement.java:228)
    at org.apache.commons.dbcp.DelegatingStatement.executeUpdate(DelegatingStatement.java:228)

我到目前为止尝试过。

  1. 增加DB中的锁定等待时间。
  2. 将序列表的类型从InnoDB更改为MyISAM。将类型更改为MyISAM后,所有作业都开始失败。但是出于不同的例外。
  3. 将作业存储库的事务隔离级别设置为ISOLATION_READ_COMMITTED
  4. 到目前为止,上述任何内容都没有帮助。请分享您的想法。

1 个答案:

答案 0 :(得分:1)

请检查您使用的是哪个数据库。如果您使用的是MySQL,那么在context.xml文件中,databaseType应该是mysql。我使用postgresql,所以我使用了postgres。接受的databaseType格式如下

<强>德比,DB2,DB2ZOS,HSQL,SQLSERVER,MYSQL,ORACLE,POSTGRES,SYBASE,H2

我的JobRepository bean如下

<bean id="jobRepository"
    class="org.springframework.batch.core.repository.support.JobRepositoryFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="transactionManager" ref="transactionManager" />
    <property name="databaseType" value="postgres" />
</bean>