【问题标题】:How does Spring Batch transaction management work?Spring Batch 事务管理是如何工作的?
【发布时间】:2015-05-31 22:14:58
【问题描述】:

我试图了解 Spring Batch 如何进行事务管理。这不是技术问题,而是概念问题:Spring Batch 使用什么方法以及该方法的后果是什么?

让我试着澄清一下这个问题。例如,查看 TaskletStep,我发现通常步骤执行看起来像这样:

  1. 几个JobRepository 事务来准备步骤元数据
  2. 每个要处理的块的业务交易
  3. 更多JobRepository 事务以使用块处理的结果更新步骤元数据

这似乎是有道理的。但是 2 和 3 之间的失败呢?这意味着业务事务已提交,但 Spring Batch 无法在其内部元数据中记录该事实。因此,即使它们已经提交,重启也会再次重新处理相同的项目。对吧?

我正在寻找对这些细节的解释以及在 Spring Batch 中做出的设计决策的后果。这是在某处记录的吗? Spring Batch 参考指南对此的细节很少。它只是从应用程序开发人员的角度解释事情。

【问题讨论】:

    标签: spring-batch


    【解决方案1】:

    Spring Batch 中有两种基本类型的步骤,一个 Tasklet 步骤和一个基于块的步骤。每个都有自己的交易细节。让我们看一下:

    基于 Tasklet 的步骤
    当开发人员实现他们自己的 tasklet 时,事务性非常简单。对Tasklet#execute 方法的每次调用都在事务中执行。您是正确的,因为在执行步骤的逻辑之前和之后都有更新。它们在技术上并未包含在事务中,因为回滚不是我们希望为作业存储库更新提供支持的东西。

    基于块的步骤
    当开发人员使用基于块的步骤时,由于增加了跳过/重试的能力,会涉及更多的复杂性。但是,从简单的层面来看,每个块都是在一个事务中处理的。由于前面提到的相同原因,您在基于块的步骤之前和之后仍然具有相同的更新,这些更新是非事务性的。

    “假设”情景
    在您的问题中,您询问如果业务逻辑完成但作业存储库的更新由于某种原因失败会发生什么。重新启动时是否会重新处理先前更新的项目。在大多数情况下,这取决于。如果您使用像FlatFileItemReader 这样的有状态读取器/写入器,则每次提交业务事务时,作业存储库都会更新为已处理内容的当前状态(在同一事务中)。因此,在这种情况下,作业的重新启动会从它停止的地方继续……在这种情况下,在最后,并且不会处理其他记录。

    如果您没有使用有状态的读取器/写入器或已关闭保存状态,那么买家要小心一点,您最终可能会遇到您所描述的情况。框架中的默认行为是保存状态,以便保留可重启性。

    【讨论】:

    • 感谢您提供这些见解。关于“假设”场景:我们使用的是有状态的 StaxEventItemReader。然而,即使在这种情况下,当然也可能是在业务事务提交时对步骤状态的更新未能提交,反之亦然。这些情况如何处理?或者我只是在这里误解了一些东西?我的观点是:JobRepository 的更新发生在与业务事务分开的事务中。因此,有可能一个提交而另一个失败,结果事情变得不同步。
    • 状态更新(也就是读者的状态)和业务交易是一回事。 只有 发生在业务事务之外的更新(因此容易不同步)是将步骤标记为已开始和已完成的更新。读取的记录数作为业务事务的一部分保留。
    猜你喜欢
    • 2014-12-01
    • 1970-01-01
    • 2021-02-07
    • 1970-01-01
    • 1970-01-01
    • 2018-02-24
    • 2013-07-30
    • 2021-02-20
    • 1970-01-01
    相关资源
    最近更新 更多