当前位置: 首页 > 知识库问答 >
问题:

事务路由和事务endpoint,事务提交顺序

潘辰龙
2023-03-14

我的路线如下

from("jms:队列:IN_QUEUE)//(A)Transacti的endpoint交易("需要")//(B)TX策略与PROPAGATION_REQUIRED和JPATxManager. bean("某豆","readFromDB()") //(C)读取DB. bean("某豆","写ToDB()") //(D)写入DB. to("file:/home/src? fileName=demo_${id}. txt")

我知道(A)处的JMS消费者将在每次轮询时分叉JMS事务,并附加到线程。(B)中的事务处理节点也将在交换到达那里并连接到线程后分叉JPA事务。

请在下面找到我的问题:

> < li >能否将两个不同的事务附加到一个线程上(如上所示)? < li >如果是,哪一个应该被停职? < li>

上述路由的提交和回滚顺序应该是什么?

注:我没有从骆驼在行动第二版中找到任何明显的答案,所以请指导我

共有2个答案

常俊爽
2023-03-14

抱歉,我无法回答您的具体问题,但我可以提供有关您路线交易的一些具体信息。

你有3个不同的“系统”,具有不同的事务“范围”

  • 您使用的 JMS 代理
  • 您从中读取和写入并为其配置了 JPA TxManager 的数据库
  • 文件系统(根本没有事务)作为目标

首先,如果希望在JMS和数据库之间实现事务安全,则必须使用XA事务。

然后,不清楚您是否希望JMS使用者进行事务处理(因为路由中的transacted()),或者您是否真的配置了具有本地JMS事务的JMS连接。我假设您确实使用了事务处理。

让我们谈谈你在没有路线B线的情况下得到了什么:

  • 您消费经纪人的交易
  • Camel通过您的路线处理消息
  • 当路由处理过程中发生任何错误时,消息不会在代理上提交,因此会重新传递到您的路由

交易消费者打开的交易由Camel保持打开状态,直到成功处理路由

因此,唯一明显的问题是数据库写入后出现错误,触发重新传递,数据库写入再次完成。可能写入不是幂等的,因此不能发生两次。

因此,为了解决这些问题,您要么必须使用XA事务,要么只使用本地JMS事务,并为上述“间隙”实现补偿逻辑

另一方面,除非必须在事务中完成读取和写入操作,否则数据库事务没有任何好处(但我怀疑两个单独的 bean 调用和一个 JMS 使用者是否就是这种情况)。

柳灿
2023-03-14

下午好

这是你另一个问题的变体。

这:

from("jms:queue:IN_QUEUE)      //(A) Transactional Endpoint

endpoint是事务性的,这意味着您已经将JMS组件标记为事务性的,并且JMS会话将由JmsTransactionManager管理。

.transacted("required")   //(B) TX Policy with PROPAGATION_REQUIRED and 
JPATxManager

这不应该是一个JPA事务管理器,而应该是一个JTA事务管理器(如阿尔诸那)。与您的另一个问题一样,您现在有一个用于读取您的消息的JMS本地事务,以及用于您的数据库访问的本地JPA事务会话。您希望平台事务管理器(JTA事务管理器)为您同步本地事务。

关于您的问题:

两个不同的事务可以附加到一个线程上吗(如上图所示)?

这真的没有任何意义。

如果是,哪一个应该被停职?

没有什么会被暂停。

上述路由的提交和回滚顺序应该是什么?

数据库读取不是事务的,不需要提交。当JTA事务上下文关闭时,文件写入实际上会发生。这就留下了数据库写入。如果失败,那么数据库读取无关紧要,消息将被放回源目标,文件写入将不会被调用。

为各种事务管理器启用DEBUG日志记录非常有帮助。

我可以痛苦地继续下去。这是给伯基的。我想你会很欣赏这个的。非常微妙,而且经常发生。

   from("jms:queue:SRC_QUEUE")
     .transacted("required")
     .to("jms1:queue:DEST_QUEUE") 

如果两个endpoint被标记为事务处理…但…您没有“事务处理”行,会发生什么?嗯,消息侦听器上启动了JMS本地事务。这将在路线结束时提交。有两个独立的本地JMS事务。这些都不是由JTA事务管理器同步的。

实际发生的情况是调用消息“get”的提交。消息“put”没有实际提交。消息“put”在JMS会话关闭时提交。这是在JMS规范中,关闭连接固有地提交任何事务。因此,因为这两个组件之间没有链接,所以提交“get”,然后关闭“put”会话。

这意味着,如果消息“get”的提交与消息“put”的会话关闭之间存在中断,则可能会丢失消息

这有意义吗?本地事务之间没有链接,所以Camel按顺序关闭它们,从调用“看跌”之前提交“get”开始。

JTA事务同步是关键。您仍然有本地事务资源(不是XA),但它们可以在非常轻量级的JTA事务上下文中得到很好的管理。

   from("jms:queue:SRC_QUEUE")
     .transacted("required")
     .to("DB:transactedwrite")
     .to("jms1:queue:DEST_QUEUE") 

我懒得查找数据库插入的正确语法,但你明白了。在这种情况下,如果 JMS“放置”失败,您可以获得重复的数据库插入。这不是“全有或全无”XA 事务。事务按顺序提交。如果中间的一个成功,那么下一个事务失败,那么“get”将被回滚,你会得到重复的,直到失败点。

 类似资料:
  • 我在我的项目中做过类似的事情。我手动回滚事务,为此我插入了try-catch块并手动回滚catch块中的事务。现在我从method1调用method2,并将对象保存到method2()中的数据库中,但它不会将对象保存到数据库中。 我只是想知道什么是可能的解决方案,保存对象在方法2()在方法1()的faliure。 提前感谢。

  • 问题内容: 我在正在使用的一个应用程序中使用Spring和Hibernate,但是在处理事务时遇到了问题。 我有一个服务类,该类从数据库中加载一些实体,修改它们的一些值,然后(当所有内容都有效时)将这些更改提交给数据库。如果新值无效(我只能在设置它们后检查),但我不想保留更改。为了防止Spring / Hibernate保存更改,我在方法中抛出异常。但是,这导致以下错误: 这是服务: 这就是我调用

  • 我在一个应用程序中使用Spring和Hibernate,我在处理事务时遇到了问题。 我有一个服务类,它从数据库加载一些实体,修改它们的一些值,然后(当一切都有效时)将这些更改提交给数据库。如果新值无效(我只能在设置它们后检查),我不想保留更改。为了防止Spring/Hibernate保存更改,我在方法中抛出一个异常。但是,这会导致以下错误: 这就是服务: 我就是这样调用它的: 我希望发生的事情是:

  • 我在使用Hibernate执行数据库更新时遇到了一个问题。当尝试repository.add(Object)操作时,它会给出一个验证异常。 我已经在模型类上添加了验证,但是我试图插入的值似乎满足了要求,所以我不知道问题出在哪里。 如果删除验证注释,repository.add(object)就可以成功完成,即。 好心看看有没有什么建议,提前谢谢。 MySQL(8.0.17)模式 Hibernate

  • 函数 A 数据操作 1; 数据操作 2; 函数 B 数据操作 3; -> 函数 A(); 函数 C 数据操作 4; -> 函数 A(); 则称,A 为 B,C 的交叉操作。 如果,A,B,C 都需要保证事务性,则 A 为 B, C 的交叉事务 Nutz.Dao 的原子操作支持事务嵌套,所以你可以这么实现这三个函数: 函数 A Tran

  • 问题内容: 我需要从存储过程中写入日志表。现在,此日志信息必须能够在回滚过程中幸免。 我知道以前曾问过这个问题,但是我的情况有所不同,在这些问题中找不到我的问题的答案。 当存储过程中没有错误时,事情就很简单了,日志表中的条目就在那里。 当有错误时,事情就变得复杂了。 在该过程中,我可以在catch中进行回滚,然后将数据插入日志表,我知道并且我已经在这样做了。 但是问题是当存储过程这样调用时: 我知