这是交易的正确行为吗?

时间:2012-12-18 07:06:06

标签: database java-ee transactions database-connection commit

我有三个在事务边界内执行的事务服务(stratTransaction或begin transaction)。所有三个服务分别使用不同的连接(No_Transaction,Local_Transaction和XA_Transaction)进行处理。现在我想知道,当我启动一个事务(使用javax.transaction.TransactionManager)并在事务边界内运行这三个服务时,我可以看到使用NO和LOCAL事务的服务能够将数据插入到表中。现在我使用Service XA在列中插入超过表约束的数据(我知道它应该失败)并调用commit(如果有任何失败则返回一个回滚过程)。现在我在NO和Local连接表的表中有数据,而XA连接表没有任何数据。现在:

我想知道当事务在某一时刻失败时,它会被要求从所有表中回滚所有数据,或者它只是要回滚XA服务的数据吗?

我也想知道:据我所知,'交易'是一种原子传输数据的过程。那么为什么连接创建包括定义可以通过连接执行的事务类型不是事务的属性呢?

我还想知道为什么我们必须在连接属性中定义事务类型,而我们必须在启动转换时定义事务类型,并且事务管理器必须执行给定类型的事务。

提前致谢。

2 个答案:

答案 0 :(得分:4)

让我们从最简单的交易模式开始,增加复杂性。

无交易

A'没有交易'连接是一个不提交的连接。或者'回滚'发送电子邮件等数据。将消息对象传递给电子邮件服务器后,它将被发送给收件人,并且任何数量的请求都不会再次收到消息。它几乎就像每次呼叫都是在呼叫返回时提交的。此类连接的示例包括与SMTP,SMS网关,打印机等的连接。

我相信你可以以这种方式使用数据库连接,如果你有自动提交,但它首先要问你为什么你有一个完整的ACID数据库......

<强>&#39;正常&#39;交易

正常连接(例如,SQL数据库)能够在内部缓冲区中存储一系列状态更改命令。当一切都已完成,并且所有内容都显示正常时,则将整个更改缓冲区写入数据存储,其他连接可以查看更改。如果在提交之前或甚至在提交期间出现问题,可以丢弃(回滚)整组更改。

此类连接的一个严重限制是缓冲区的范围 - 缓冲区是连接本身的一部分。换句话说,只有通过连接才能写入缓冲区。

应用程序服务器的一项重要职责是管理这些连接。当您要求连接池为您提供连接时,您每次都会神奇地获得相同的连接(在单个事务中)。即使在一个EJB调用另一个EJB或EJB调用资源适配器时(假设您使用REQUIRES_TRANSACTION语义),也是如此。您可以使用REQUIRES_NEW覆盖它。此行为意味着一个Web请求可以进行多个EJB调用,每个EJB调用都可以与多个实体bean进行交互,并且所有数据操作都在具有单个内部缓冲区的单个连接上进行。它将全部承诺或回滚。

多个连接的交易

当您拥有单个数据库时,这很棒 - 但是(根据定义)如果您与单独的数据库实例(例如,在不同的计算机上)进行通信,则需要单独的连接。那会发生什么呢?您的EJB事务最终与多个连接相关联 - 每个连接都与一个唯一的数据库相连。除了在一种情况下,这似乎运作良好:

  • 您有连接A到数据库A和连接B到数据库B
  • 您在A和B上执行DML语句
  • 您提交EJB连接。 Application Server现在:
    1. 提交连接A - 成功
    2. 提交连接B - 失败(例如约束失败)和连接B回滚

这是一场灾难 - 您已在数据库A中提交了该事务,现在无法回滚。但是,事务(以及整个EJB)将在数据库B上回滚。

(有趣的是,您的示例几乎与此相同 - 您将数据提交到无交易和正常交易,但不在XA交易中 - 三个连接的最后

XA交易

这就是XA的用武之地。它提供了逻辑来协调针对不同数据源提交的事务模拟多个数据源上的单个事务。 XA提交了一个&#34;两阶段提交&#34;由交易协调员管理,该协调员管理多个加入XA交易的XA连接。协调员

  1. 通过XA Connection向每个数据源发送消息,以查看事务是否可以提交:所有约束和数据库逻辑在最终提交之前执行。如果任何数据库报告失败,XA协调员将回滚整个事务。阶段1是几乎所有交易工作都在进行的地方,所以需要相当长的时间
  2. 当每个数据库报告事务可以提交时,协调员会向每个数据库发送一条消息以提交事务。这种情况发生得非常快。
  3. 请注意,如果第2阶段出现问题,则两阶段提交可能会失败(例如,部分网络崩溃或其中一个数据库在阶段1和阶段2之间断电)。 / p>

    由于XA连接的行为与普通连接的行为不同,因此它通常需要一个不同的ConnectionFactory对象,该对象实例化的对象实例不同于非XA ConnectionFactory。此外,XA ConnectionFactory需要XA事务协调器的配置参数,例如XA事务超时,这是普通事务属性的补充。

    另一个约束:只有XA ConnectionFactory创建的Connections才能加入XA事务和相关的两阶段提交。您可以同时参与单个Application Server事务的XA和非XA连接,但是整个事务无法作为单个事务可靠地提交/回滚(如上所述)。

    具体答案

      

    我想知道,当事务在某一时刻失败时,它会被要求从所有表中回滚所有数据,或者只是回滚XA服务的数据?

    如果事务在应用程序服务器尝试提交之前失败(例如,您的EJB获得NPE或您故意回滚),则每个连接都将收到回滚,并且所有内容都应该如您所愿。

    但是,如果事务在提交逻辑中失败(例如数据库约束),那么事务管理器将尝试回滚所有内容;如果非XA连接已经提交,则不会发生这种情况。

      

    我也想知道:&#39;交易&#39;据我所知,这是一个以原子方式传输数据的过程。那么为什么连接创建包括定义可以通过连接执行的事务类型不是事务的属性?

    XA连接使用与普通连接不同的库和协议,因为连接本身需要与XA事务协调器通信。正常连接不会这样做。

      

    我还想知道为什么我们必须在连接属性中定义事务类型,而我们必须在启动事务时定义事务类型,并且事务管理器必须执行给定类型的事务。

    由于XA连接使用不同的代码,因此与普通连接相比,连接池需要加载不同的类。这就是连接池(非连接)属性不同的原因。

答案 1 :(得分:0)

是的,如果事务未能在日志文件中写入其提交条目,则它完全回滚(trxn的原子属性)。

Trxn是数据库处理的原子单元。无论您使用txn在数据库中执行什么操作,该操作都将是原子操作。 默认情况下,事务是自动提交类型。但如果您使用自己的代码来说明txn的起点和提交点,则它是显式类型。(http://msdn.microsoft.com/en-us/library/ms172353.aspx)