跳到主要内容

执行XA事务操作

一旦建立了XA会话,就必须获取该XA会话的XA资源,以创建和管理事务分支(参见获取XA资源)。

XA资源接口定义了资源管理器和事务管理器在分布式事务处理(DTP)环境中的契约,以及它提供的方法允许事务管理器管理事务分支并控制其状态。

事件代理作为资源管理器,将代表事务管理器执行事务分支所请求的工作。资源管理器负责将所有在其数据上在开始和结束方法调用之间执行的工作与全局事务相关联。

Xids

XA资源使用Xids来标识每个事务分支。这些Xids必须在消息VPN中是唯一的。

Xid由全局事务ID(一个1到64字节的数组)组成,该ID标识事务将参与的全局事务,以及全局事务格式ID(一个4字节的数组)和分支限定符ID(一个1到64字节的数组),该限定符唯一标识事务分支。Xid由所有三个字段组成,字段之间用“-”字符分隔:

<格式ID>-<全局事务ID>-<分支限定符>

每个字段以ASCII十六进制格式显示,数组中的每个字节对应两个ASCII字符。ASCII十六进制字符的数量暗示了数组的长度。XID最多可以有266个字符长。

以下是在Solace CLI输出中可能出现的Xids示例:

01020304-0123456789ABCDEF-01
00020304-01-02
02030405-00-03
09ABCDEF-0000-04
01020304-000000-05

全局事务标识符和分支限定符的组合对于每个Xid必须是全局唯一的,尽管格式ID通常为零,这表明使用了OSI CCR(开放系统互连承诺、并发和恢复)标准进行命名。

javax.transaction.xa.Xid接口被使用XA事务的Java应用程序使用。通常,Xid接口由事务管理器用于与资源管理器协调(事件代理作为资源管理器)。然而,Solace JMS包提供了一个此接口的实现(com.solacesystems.common.xa.SolXid),以便于可能在没有应用服务器的情况下开发XA应用程序的程序员使用。

事务状态

可以通过XA资源为事务执行的操作以及这些操作可以发生的顺序,由事务分支的当前状态决定。下表列出了根据对其执行的XA请求,事务分支可能具有的状态。

事务状态描述
活动事务与XA会话相关联。在所有其他状态中,事务不与XA会话相关联。事务在通过调用XAResource.start(...)成功创建后具有活动状态。具有活动状态的事务只要XA会话打开就会持续存在。
空闲事务未与XA会话相关联,如果在空闲超时期间内未准备好、提交或回滚,将被回滚。事务在通过调用XAResource.end(...)成功结束后具有空闲状态。
已准备事务已准备好,可以提交或回滚。事务在通过调用XAResource.prepare(...)成功准备后具有已准备状态。
启发式完成事务已启发式完成,并已成功提交或回滚。事务在管理员成功启发式提交或回滚事务后具有启发式完成状态。启发式完成的事务将持续存在,直到通过调用XAResource.forget(...)将其删除,或者管理员通过Solace CLI或SolAdmin启发式删除事务。
空闲事务未分配。

可能的事务状态

下表指示在进行特定XA资源请求时事务必须具有的状态,以及请求成功后事务将具有的状态。

事务状态只有在所有必需的处理完成后才会改变。例如,当发出XA准备请求时,事务状态将保持在空闲状态,直到事务中所需的所有操作完成并且准备请求成功完成。或者,如果准备失败,事务将被回滚,因此从未转换为已准备状态。有关更多信息,请参阅准备事务。

XA请求可在事务具有以下状态时调用成功调用后事务状态...
XAResource.start与TMNOFLAG空闲活动
XAResource.start与TMNORESUME空闲(挂起)活动
XAResource.end与TMFAIL活动或空闲空闲(仅回滚)
XAResource.end与TMSUCCESS活动或空闲空闲
XAResource.end与TMSUSPEND活动空闲(挂起)
XAResource.prepare空闲已准备
XAResource.commit已准备空闲
XAResource.commit与onePhase空闲空闲
XAResource.rollback活动、空闲或已准备空闲

XA请求及相关事务状态

获取XA资源

要获取用于XA会话的XA资源,请调用XASession.getXAResource()

默认情况下,资源管理器为XA资源使用的事务超时值为180秒。要为获取的XAResource实例设置事务超时值(以秒为单位),请调用XAResource.setTransactionTimeout(int seconds)并传入秒数的值。要将超时值重置为资源管理器使用的默认值,请将值设置为零。

可以使用获取的XA资源执行以下主要操作:

  • 启动事务
  • 结束事务
  • 准备事务
  • 完成或取消事务
  • 关闭XA会话

启动事务

要将事务分支与资源关联,并开始代表指定Xid的事务分支的工作,必须调用XAResource.start(Xid xid, int flags)方法。

在事务分支中最多可以跟踪256条消息。这些包括要添加到端点的已发布消息,和/或暂存在端点上要被消费并从这些端点移除的消息。

要启动事务,请调用以下方法:

XAResource.start(Xid xid, int flags)

其中:

xid是事务的Xid。

flags是以下之一:

  • TMNOFLAGS—表示事务是一个要启动的新事务。XID在消息VPN中必须唯一,且事务不能已经与XA会话相关联,否则请求将被拒绝。
  • TMRESUME—表示事务是一个要恢复的挂起事务。XID必须处于挂起状态,否则请求将被拒绝。

Solace JMS实现不支持TMJOIN标志,该标志表示要执行的工作将被添加到另一个预先存在的事务中。

start(...)成功调用时,将在XA会话和事务分支之间创建关联,事务分支将处于活动状态。

一次只能将一个分布式事务与XA会话相关联。

结束事务

XA结束请求用于结束或挂起具有活动状态的事务分支正在进行的工作。调用此方法时,将向资源管理器(即事件代理)发送XA结束请求以:

  • 将已发布和消费的消息与给定Xid标识的事务分支相关联;
  • 将XA资源与该事务分支分离;
  • 然后让事务完成。

要结束或挂起具有活动状态的事务分支正在进行的工作,请调用以下方法:

XAResource.end(Xid xid, int flags)

其中:

xid是事务的Xid。

flags是以下之一:

  • TMSUCCESS—表示事务中的工作部分已成功完成
  • TMSUSPEND—表示事务暂时挂起在未完成状态
  • TMFAIL—表示事务中的工作部分已失败

end(...)成功调用在活动事务分支上时,结果取决于为该方法设置的标志:

  • TMSUCCESS标志—事务的状态更改为空闲(如果事务的空闲时间超过为XAResource设置的空闲超时值,事务将自动回滚)。然后事务可以准备进行两阶段提交,或者通过一阶段提交提交,或者回滚。
  • TMSUSPEND标志—事务的状态更改为空闲。事务分支与XA会话之间的关联从已关联更改为挂起关联。
  • TMFAIL标志—事务的状态更改为空闲,标记为仅回滚,只能通过回滚释放。

当设置TMSUCCESSTMSUSPEND标志时,如果在发出XA结束请求之前,订阅者消息的端点已关闭或删除,或者要消费的消息已在不同流中被消费或重新投递,则请求将失败。当XA结束请求失败时,事务将进入空闲状态并标记为仅回滚——它只能通过回滚释放。

end(...)未成功调用时,事务将自动回滚,并向客户端API返回XA_RBROLLBACK响应。

准备事务

已结束且处于空闲状态的事务分支在可以通过两阶段提交提交之前必须先准备好。

要准备空闲事务以提交,请调用以下方法:

XAResource.prepare(Xid xid)

其中:

xid是事务的Xid。

当发出XA准备调用时,事件代理将验证请求,然后处理分配给事务的消息列表,并将请求的结果以响应消息的形式发送给客户端(例如,XA_OKXA_RBROLLBACK)。

prepare(...)成功调用时,事务的状态更改为已准备,XA会话和事务不再相关联。成功准备的事务有很大概率可以成功提交。

prepare(...)未成功调用时,将抛出XAException,事务将自动回滚并释放。

在分布式事务中没有其他资源参与的情况下,只需要一阶段提交,客户端不需要调用XAResource.prepare(...)。在这种情况下,客户端可以直接调用commit(...),并将onePhase标志设置为true

当执行XA准备并且事务分支中的消息要消费或发布的端点已关闭、超出其消息配额或已删除时,会发生以下情况:

  • 如果在发出XA准备调用时,事务分支中的消息要消费的端点已关闭、删除或超出其消息配额,则事务将失败并回滚。
  • 如果在发出XA准备调用之前,事务分支中的消息要发布或消费的端点已被删除,则准备将失败,事务将回滚。
  • 如果在发出XA准备调用时,事务分支中的消息要发布的端点已关闭或超出其消息配额,则会发生以下情况:
    • 如果端点启用了reject‑to‑sender‑on‑discard参数(这是默认设置),事务将失败并回滚。
    • 如果端点未启用reject‑to‑sender‑on‑discard参数,则准备将成功,但在调用提交时,消息不会添加到端点。

在执行XA准备请求时进行配额检查,检查会考虑事务中的所有消息,但不会考虑其他已准备事务中的任何消息。

完成或取消事务

通过XA事务发布或接收的消息会被暂存于事件代理。事务可以通过以下方式处理:

  • 通过提交操作完成。
  • 通过回滚操作取消。

提交事务

要提交事务,请调用以下方法:

XAResource.commit(Xid xid, boolean onePhase)

其中:

xid是事务的Xid。

onePhase是一个标志,指示资源管理器是否应使用一阶段提交协议来提交代表Xid完成的工作。如果为true,资源管理器必须使用一阶段提交协议来提交代表Xid完成的工作。如果为false,资源管理器必须使用两阶段提交协议来提交代表Xid完成的工作。

只有当事务分支处于空闲状态(需要一阶段提交)或已准备状态(需要两阶段提交)时,才能提交事务分支。

当事务分支成功提交时,会发生以下情况:

  • 对于发布操作,暂存的消息将被发送到其目标队列或主题(即持久主题端点)。
  • 对于接收操作,消费者将确认接收到的消息,然后从暂存这些消息的端点移除这些消息。
  • 事务的状态更改为空闲。

提交是阻塞操作。在当前事务通过成功提交释放之前,或者事务被回滚或挂起之前,不能启动新事务。

提交的结果将通过响应消息发送给客户端API。如果提交因任何原因失败,整个事务将回滚。将抛出XAException以指示失败原因。

当执行提交并且事务分支中的消息要发布的端点已关闭或删除时,会发生以下情况:

  • 对于一阶段提交:
    • 当端点关闭时:如果端点配置为reject-to-sender-on-discard,则事务将回滚。如果未启用reject‑to‑sender‑on‑discard,则提交成功,但消息不会添加到端点。
    • 当端点删除时:提交失败,事务将回滚。
    • 如果提交失败,资源管理器可能会抛出XA_RB*异常。在这种情况下,资源管理器将回滚分支的工作并释放所有持有的资源。
  • 对于两阶段提交:
    • 当端点关闭时:提交成功,但消息不会添加到端点。
    • 当端点删除时:提交成功。

回滚事务

客户端可以通过调用XAResource.rollback()来回滚处于活动、空闲或已准备状态的事务,而不是通过提交完成活动事务。

当执行回滚时,将移除活动事务的暂存信息,因此:

  • 对于发布操作,发布者消息将从消息暂存区删除,并且不会暂存到目标端点,事务将被释放。
  • 对于消费操作,分配给事务的消息将保留在端点的暂存区中,它们将被重新投递,事务将被释放。

回滚是阻塞操作。

rollback(...)成功调用时,事务的状态将更改为空闲。

如果由于网络故障或事件代理重置导致事务会话失败,客户端可以立即重新连接(如果客户端连接的重连尝试次数大于零,则此操作是自动的),并且如果可能的话,API将重新建立正在进行的事务。如果会话和事务在三分钟内没有重新建立,事件代理将自动回滚正在进行的事务。(有关设置客户端重连属性的信息,请参阅配置连接超时和重试。)

删除启发式完成的事务分支

如果要删除由事件代理管理员启发式完成的事务分支,可以执行XAForget请求。只有当事务已启发式提交或回滚,并且事务被释放时,此请求才能成功执行。

要删除启发式完成的事务分支,请调用以下方法:

XAResource.forget(Xid xid)

其中:

xid是事务的Xid。

有关事件代理管理员可用的启发式操作的信息,请参阅对事务执行启发式操作。

恢复已准备的事务

如果应用服务器发生故障,可以使用XAResource.recover(…)方法要求事件代理返回处于已准备或启发式完成状态的事务分支。

XAResource.recover(int flags)

其中:

flags是以下之一:

  • TMSTARTRSCAN—开始恢复扫描。
  • TMENDRSCAN—结束恢复扫描。
  • TMNOFLAGS—表示未选择任何标志值。当参数中未设置其他标志时,必须使用TMNOFLAGS