代码之家  ›  专栏  ›  技术社区  ›  Yanick Salzmann

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

  •  1
  • Yanick Salzmann  · 技术社区  · 6 年前

    让我们考虑以下上下文:

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

    为了确保在触发第二个通道之前完全提交来自通道1的事务,我们将 JpaTransactionManager 正在注册 TransactionSynchronization prepareForCommit 它重写的方法 JPA事务管理器

    流程(通道1)如下所示:

    • 做所有的消息处理和数据库处理
    • 流的最后一步寄存器A 事务同步 这样做了 MessageChannel.send afterCommit 向通道2发送消息的阶段

    我的理解是,在消息发送到第二个频道时 事后承诺 )已在通道1的数据库事务中完成的所有更改都将被刷新并提交。

    现在,第二个通道完成了一些工作(如mq-put),然后更新在第一个流中创建的条目。我们现在已经注意到,repository方法在数据库中没有返回任何条目,但稍后它在表中可见。但是,在第一个通道的事务中也创建的其他条目是可见的。这只发生在每几千条消息中一次,通常它们在那里,但有时在通道1提交事务后的几毫秒内,它们在第二个通道中不可见。

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

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

    我注意到的一件事是,有时存在有时不存在的条目都在(非故意)使用的一种方法中 javax.transaction.Transactional 而不是 org.springframework.transaction.annotation.Transactional . 但是,我们正在使用 弹簧芯5.0.8.释放 在其他问题中,我已经看到,这应该是从Spring4.2.x开始的0差异。

    1 回复  |  直到 6 年前
        1
  •  1
  •   Artem Bilan    6 年前

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

    应该有足够的服务激活器来为pojo方法标记 @Transactional . 这样,一个事务将围绕这个方法调用开始和结束。方法的结果将在事务提交之后被发送到输出通道。

    更新

    达到你要求的最好方法是 <gateway> 围绕着你的链条1。这样,在从网关生成对chain2的回复之前,Tx将在那里提交。

    TransactionSynchronization::afterCommit 当QueueChannel准备好轮询消息时,不能保证在DB上提交Tx。虽然你可以用 JdbcChannelMessageStore 用于消息的事务存储。这样,在Tx在DB中提交之前,它们是不可见的。

    更多地了解 <网关& GT; 在文档中: https://docs.spring.io/spring-integration/docs/current/reference/html/messaging-routing-chapter.html#_calling_a_chain_from_within_a_chain