我试图了解 Spring Batch 如何进行事务管理。这不是技术问题,而是概念问题:Spring Batch 使用什么方法以及该方法的后果是什么?
让我试着澄清一下这个问题。例如,查看 TaskletStep,我看到通常一个步骤执行看起来像这样:
这似乎是有道理的。但是如果失败在 2 到 3 之间呢?这意味着业务事务已提交,但 Spring Batch 无法在其内部元数据中记录该事实。因此,即使它们已经提交,重新启动也会再次重新处理相同的项目。对?
我正在寻找对这些细节的解释以及在 Spring Batch 中做出的设计决策的后果。这是在某处记录的吗? Spring Batch 引用指南对此的详细信息很少。它只是从应用程序开发人员的角度解释事情。
最佳答案
Spring Batch 中有两种基本类型的步骤,Tasklet 步骤和基于块的步骤。每个都有自己的交易细节。让我们来看看每个:
基于 Tasklet 的步骤
当开发人员实现他们自己的 tasklet 时,事务性非常简单。每次调用Tasklet#execute
方法在事务中执行。您是正确的,因为在执行步骤的逻辑之前和之后都有更新。从技术上讲,它们并未包含在事务中,因为回滚不是我们希望为作业存储库更新提供支持的内容。
基于块的步骤
当开发人员使用基于块的步骤时,由于增加了跳过/重试的能力,因此涉及更多的复杂性。然而,从简单的层面来看,每个块都是在一个事务中处理的。由于前面提到的相同原因,在基于块的步骤之前和之后,您仍然具有相同的更新,这些更新是非事务性的。
“假设”场景
在您的问题中,您询问如果业务逻辑完成但由于某种原因对作业存储库的更新失败会发生什么。是否会在重新启动时重新处理先前更新的项目。在大多数情况下,这取决于。如果您使用像 FlatFileItemReader
这样的有状态读取器/写入器,随着业务事务的每次提交,作业存储库都会更新为已处理内容的当前状态(在同一事务中)。因此,在这种情况下,作业的重新启动会从停止的地方开始……在这种情况下是在最后,并且不处理其他记录。
如果您没有使用有状态的读取器/写入器或关闭了保存状态,那么买家要小心了,您最终可能会遇到您所描述的情况。框架中的默认行为是保存状态,以便保留可重启性。
关于spring-batch - Spring Batch 事务管理如何工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29303155/