Spring Batch 无法获取 last_insert_id();嵌套异常是 java.sql.SQLException: Lock wait timeout exceeded;

Posted

技术标签:

【中文标题】Spring Batch 无法获取 last_insert_id();嵌套异常是 java.sql.SQLException: Lock wait timeout exceeded;【英文标题】:Spring Batch Could not obtain last_insert_id(); nested exception is java.sql.SQLException: Lock wait timeout exceeded; 【发布时间】:2015-12-05 17:02:14 【问题描述】:

我在 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)

到目前为止,我尝试关注。

    增加 DB 中的锁等待时间。 将序列表的类型从 InnoDB 更改为 MyISAM。将类型更改为 MyISAM 后,所有作业都开始失败。但是对于不同的例外情况。 将作业存储库的事务隔离级别设置为 ISOLATION_READ_COMMITTED

到目前为止,上面没有任何帮助。请分享您对此的看法。

【问题讨论】:

【参考方案1】:

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

DERBY、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>

【讨论】:

以上是关于Spring Batch 无法获取 last_insert_id();嵌套异常是 java.sql.SQLException: Lock wait timeout exceeded;的主要内容,如果未能解决你的问题,请参考以下文章

Spring boot spring.batch.job.enabled=false 无法识别

Spring boot spring.batch.job.enabled=false 无法识别

无法打开spring-batch-core

Spring Batch Admin + Spring Boot - 不明确的映射。无法映射“org.springframework.batch.admin.web.JobController#1”方

Spring Batch Test - 无法自动装配。找不到“JobLauncherTestUtils”类型的 bean

在获取所有数据之前,Spring Batch ResultSet 已被其他人关闭