【问题标题】:Two Phase Commit/Shared Transaction两阶段提交/共享事务
【发布时间】:2008-09-18 01:56:28
【问题描述】:

场景是这样的

我们有两个应用程序 A 和 B,它们都在单独的数据库 (Oracle 9i) 事务中运行

应用程序 A - 将一些数据插入数据库,然后调用应用程序 B 应用程序 B - 将一些数据插入到数据库中,与 A 的数据相关(通过外键)。向应用程序 A 返回一个“ID” 应用程序 A - 使用 ID 插入更多数据,包括来自 B 的 ID

现在,因为这些是单独的事务,但都依赖于彼此事务的数据,所以我们需要在对每个应用程序的调用之间提交。如果出现任何问题,这当然会使回滚变得非常困难。

您将如何解决这个问题,同时对代码进行最少的重构。这种情况肯定是 SOA 世界的普遍问题吗?

--------更新--------

我在 Oracle 9i 中找不到任何东西,但是 Oracle 11g 提供了DBMS_XA,这正是我所追求的。

【问题讨论】:

  • 我认为这些标签不相关。问题中甚至没有提到 java、perl、jboss,而且问题并非特定于 oracle。

标签: oracle


【解决方案1】:

您有三个选择:

  1. 重新设计应用程序,这样您就不会有两个不同的进程(都具有数据库连接)写入数据库并将其整合到一个应用程序中。

  2. 创建处理 A 和 B 的所有数据库事务的应用程序 C。

  3. 滚动您自己的两阶段提交。应用程序 C 充当协调器。 C 向 A 和 B 发出信号,询问他们是否准备好提交。 A 和 B 进行处理,并以“就绪”或“失败”回复响应 C(请注意,如果一个进程挂起或死亡,C 上应该有一个超时以避免无限等待)。如果双方都准备好回复,则 C 告诉他们提交。否则它会发送一个回滚信号。

请注意,如果应用程序 A 依赖于应用程序 B 的外键(您没有说明,因此这可能不是问题),您可能会遇到选项 3 的问题。 Oracle 的读取一致性可能会阻止这种情况发生,因为应用 A 的事务将在应用 B 之前开始。只是一个警告。

【讨论】:

  • 我担心会出现这种情况,希望有人知道我不知道的事情。会等着看其他人有没有什么神奇的东西可以提供,如果没有,会接受答案。
【解决方案2】:

一些建议:

  • 使用Compensating transactions。基本上,您可以撤消之前执行的事务。困难的部分是确定要回滚的事务。

  • 使用指示它只是临时的标志将应用程序 A 和 B 的数据提交到数据库。然后,在一切检查正常后,修改标志以指示数据是最终的。在夜间,运行批处理作业以清除尚未完成的数据。

【讨论】:

  • 注意:第二个选项会使“世界”处于不一致的状态:A 可能有一个已完成的交易,而B 没有相应的交易。最好使用两阶段提交来完成。
【解决方案3】:

您可能可以将来自应用程序 A 的数据插入“临时”区域,以便应用程序 B 可以同时插入 A 和 B,而不会在任何一个应用程序中进行太多更改。它不是特别优雅,但它可能会奏效。

在另一种情况下,您可以在数据中添加一个“确认”标志字段,该字段在整个过程成功运行后更新。如果它在某一时刻失败,则可能更容易追踪您需要回滚(实际上是删除)的记录。

【讨论】:

    【解决方案4】:

    我喜欢提出的两种解决方案,所以我暂时避免发布此内容。但是您也可以对主表进行更新,事先将受影响行的状态保存在某个缓存中。

    这可以与两层(Zathrus 提出的交通警察系统)结合使用——因为对于 neonski 使用“画板”表格或表格的解决方案来说确实不需要它。这样做的缺点是,您必须让您的过程/逻辑从工作区或主表的工作区查询主表 - 或者可能将您的标志存储在主表中并在您将数据提交到时将其设置回主表。

    我们团队的一位女士正在使用永久性工作台为我们的实时系统设计类似的东西。

    【讨论】:

      【解决方案5】:
      App_A =={0}=>               database # App_A stores information for App_B
      App_A ------> App_B                  # App_A starts App_B
                    App_B <={0}== database # App_B retrieves the information
                    App_B =={1}=> database # App_B stores more informaion
      App_A <={2}== App_B                  # App_B returns 'ID' to App_A
      App_A ={2,3}>               database # App_A stores 'ID' and additional data
      

      只是我还是看起来应用程序 B 本质上只是 A 的子程序。我的意思是应用程序 B 在 A 询问之前什么都不做,而应用程序 A 在 B 返回 ID 之前什么也不做。这意味着将它们放在不同的应用程序甚至单独的线程中毫无意义。

      【讨论】:

      • 应用程序A将数据插入B所需的数据库中,然后插入更多从B返回的数据。
      • 我知道它实际上是如何工作的,我只是想用更抽象的方式来解释它。
      猜你喜欢
      • 2014-03-16
      • 2018-08-15
      • 2011-11-15
      • 2011-11-24
      • 2013-05-21
      • 1970-01-01
      • 2016-01-04
      • 1970-01-01
      相关资源
      最近更新 更多