java - 事务更改的子集有时在提交后不久不可见

标签 java spring transactions spring-integration

让我们考虑以下上下文:

2个spring集成 channel ,它们各自位于单独的数据库事务中。在第一个事务结束时,一条消息被放入第二个 channel 中。在第一个 channel 中,在数据库中创建元素,随后由从第一个 channel 发送到第二个 channel 的相应消息使用这些元素。

为了确保在触发第二个 channel 之前完全提交来自 channel 1 的事务,我们 JpaTransactionManager 的子类正在注册 TransactionSynchronizationprepareForCommit它从 JpaTransactionManager 覆盖的方法

流程( channel 1)如下所示:

  • 完成所有消息处理和数据库处理
  • 流程的最后一步注册 TransactionSynchronization这样做是 MessageChannel.sendafterCommit将消息发送到 channel 2 的阶段

我的理解是,当消息发送到第二个 channel (在 afterCommit 中)时, channel 1 的数据库事务中所做的所有更改都将被刷新并提交。

现在,第二个 channel 执行一些工作(如 MQ PUT),并稍后更新在第一个流中创建的条目。我们现在观察到存储库方法在数据库中没有返回任何条目,但稍后在表中可见。然而,也在第一个 channel 的交易中创建的其他条目是可见的。这种情况每几千条消息才会发生一次,通常它们在那里,但有时在 channel 1 提交事务几毫秒后,它们对第二个 channel 不可见。

我创建了一个图像来说明它: enter image description here

Chain 1是第一个由多个 ServiceActivators 组成的链执行数据库工作,一个生成更多消息的拆分器,然后生成另一个 ServiceActivator我命名为SENDER它注册了 TransactionSynchronization (据我的理解)应该在红色事务完全提交之后(因此在蓝色事务开始之前)将例如 3 条生成的消息发送到链 2。

我注意到的一件事是,有时存在、有时不存在的条目都在(不是故意)使用 javax.transaction.Transactional 的一种方法中。而不是org.springframework.transaction.annotation.Transactional 。但是,我们正在使用 spring core 5.0.8.RELEASE,在其他问题中我发现,自 spring 4.2.x 以来,这应该产生 0 差异。

最佳答案

我不认为afterCommit是向下游发送消息的正确位置。

应该足以让 POJO 方法的服务激活器标记为 @Transactional 。这样,事务将完全围绕该方法调用开始和结束。该方法的结果将在事务提交后立即发送到输出 channel 。

更新

实现您的要求的最佳方式是 <gateway>围绕您的 Chain1。这样,在从网关向 Chain2 生成回复之前,TX 将被提交到那里。

TransactionSynchronization::afterCommit当 QueueChannel 准备好轮询消息时,无法保证 TX 将在 DB 上提交。虽然您可以使用 JdbcChannelMessageStore用于消息的事务存储。这样,在 TX 在数据库中提交之前,它们将不可见。

查看更多有关<gateway>的信息在文档中:https://docs.spring.io/spring-integration/docs/current/reference/html/messaging-routing-chapter.html#_calling_a_chain_from_within_a_chain

关于java - 事务更改的子集有时在提交后不久不可见,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54630155/

相关文章:

java - spring-boot-starter-oauth2-resource-server vs spring-cloud-starter-oauth2 使用哪个?

multithreading - 我如何在Neo4j中使用并行事务?

java - 如何在 cucumber-jvm 步骤之间传递变量

java - 具有 DTO 和 EO 的 DRY 原则,用于启用 spring 和 hibernate 的 webapp

java - Spring 数据 JPA : Named method without JpaRepository

java - Hibernate异常: saveOrUpdate is not valid without active transaction

java - Spring 启动 : save to repository doesnt work with @Transactional(propagation = Propagation. REQUIRES_NEW)

java - 以毫秒为单位获得实际的 DST 节省

java - 如何修复这个错误的操作数 (&&)

java - 如何从具有多个组合的字符串中获取 token