春季批处理中的OptimisticLockingFailureException

时间:2019-09-02 07:36:01

标签: java spring-batch

我正遇到 org.springframework.dao.OptimisticLockingFailureException:尝试使用错误的版本(0)更新步骤执行id = xxx,其中当前版本为0 。它正在运行,最近它开始启动任何春季批处理作业时都引发此异常(我们使用Spring批处理从excel批量导入,从数据库导出文件,共有6个作业)

异常是从第一步开始抛出的,由于昨天运行良好,因此仅从昨天开始发生。 相同的代码可在不同的环境中工作。

深入研究Spring批处理源代码,我发现它试图使用where子句中的step_execution_id和version更新行,但没有行被更新。 然后,它抛出此异常以通知是否有任何并发​​修改。 但是它要更新的版本是0,当前版本也是0。 正如许多人问的那样,但是更新版本和当前版本有所不同,在我看来,这是相同的。

我正在使用Spring 3.8.0和Hibernate 5.4.1。

我还尝试了清除spring批处理表。 尝试重新启动,重新部署等。

PS-请原谅我的英语。

3 个答案:

答案 0 :(得分:0)

删除弹簧批处理表并重新创建它们对我来说解决了这个问题。

答案 1 :(得分:0)

答案不是我真正的回答,我只是引用我的朋友,他的公司也有同样的问题(这也是预期的= 0 current = 0):

我们遇到了同样的问题,因为我们的类路径中有2个不同版本的oracle驱动程序。当我们删除其中一个时,问题就解决了。

答案 2 :(得分:0)

OptimisticLockingFailureException 当 2 个作业同时针对不同的数据服务器运行时发生。 看起来以下 BATCH 表被创建为复制表。

  1. BATCH_JOB_EXECUTION
  2. BATCH_JOB_EXECUTION_CONTEXT
  3. BATCH_JOB_EXECUTION_PARAMS
  4. BATCH_JOB_EXECUTION_SEQ
  5. BATCH_JOB_INSTANCE
  6. BATCH_JOB_SEQ
  7. BATCH_STEP_EXECUTION
  8. BATCH_STEP_EXECUTION_CONTEXT
  9. BATCH_STEP_EXECUTION_SEQ

作业序列 id 和执行 id 是通过分别增加 BATCH_JOB_EXECUTION_SEQ 和 BATCH_JOB_SEQ 表中的当前值来创建的。 当您同时针对不同的数据服务器运行作业时,这会导致问题,因为两个作业在技术上可以具有相同的作业执行 ID。

在我们的应用程序中,我们遇到了同样的问题。 JOB1JOB2 同时启动。 JOB1 针对 DATASERVER1 启动,JOB2 针对 DATASERVER2 启动。在我们的例子中,JOB1JOB2 使用相同的执行 ID 20000002345,这从 DATASERVER1 和 <强>DATASERVER2。 这导致 JOB1 失败,因为步骤表中的版本已在 DATASERVER2 中途更改。我们得到了以下异常。

例外: org.springframework.dao.OptimisticLockingFailureException:尝试使用错误版本 (1) 更新步骤异常 id=20000002345,当前版本为 2

JOB2 也由于重复的步骤执行 ID 失败。

例外: 引起:org.springframework.dao.DuplicateKeyException: PreparedStatementCallback; SQL [插入 BATCH_JOB_INSTANCE(JOB_INSTANCE_ID, JOB_NAME, JOB_KEY, VERSION) 值 (?, ?, ?, ?)];密钥 1 的重复条目“1”;嵌套异常是 com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: 键 1 的重复条目“1”

解决方案: 我们要求 DBA 在所有数据服务器(DATASERVER1、DATASERVER2、DATASERVER3 等)上关闭BATCH 表的复制(9 个以上的表)。 这解决了问题。在我们关闭复制后,这个问题就再也没有发生过。