云数据库OceanBase入门教程 OceanBase XA 组件

2024-02-26 开发教程 云数据库OceanBase入门教程 匿名 2

XA 组件是 OceanBase Connector/J 指定的标准 XA 接口。

XADatasource 接口和 Oracle 实施

javax.sql.XADataSource接口概述了 XA 数据源的标准功能,是 XA 连接的工厂。getXAConnection方法重载返回一个 XA 连接实例,并可以选择使用用户名和密码作为输入,如下所示:

public interface XADataSource
{
XAConnection getXAConnection() throws SQLException;
XAConnection getXAConnection(String user, String password)
throws SQLException;
...
}

OceanBase Connector/J 使用 OracleXADataSource类实现 XADataSource接口。OracleXADataSource类还扩展了 OracleConnectionPoolDataSource类,而 OracleConnectionPoolDataSource类扩展了 OracleDataSource类,因此包括所有连接属性。

OracleXADataSource类的 getXAConnection方法返回 XA 连接实例的 Oracle 实现,这些实例是 OracleXAConnection实例。

说明
您可以使用前面讨论的非池化数据源相同的命名约定在 Java 命名目录和接口(JNDI)中注册 XA 数据源。

XAConnection 接口和 Oracle 实施

XA 连接实例与池连接实例一样,封装了与数据库的物理连接。 这里的数据库是指在产生 XA 连接实例的 XA 数据源实例的连接属性中指定的数据库。

每个 XA 连接实例还具有生成 OracleXAResource实例的功能,该实例将与之相对应以用于协调分布式事务。

XA 连接实例是实现标准 javax.sql.XAConnection接口类的实例,如下所示:

public interface XAConnection extends PooledConnection
{
javax.jta.xa.XAResource getXAResource() throws SQLException;
}

XAConnection接口扩展了 javax.sql.PooledConnection接口,因此还包括 getConnectioncloseaddConnectionEventListenerremoveConnectionEventListener方法。

JDBC 使用 OracleXAConnection类实现 XAConnection接口,OracleXAConnection类还扩展了 OraclePooledConnection类。

OracleXAConnection类的 getXAResource方法返回 OracleXAResource实例的 Oracle 实现,该实例是一个OracleXAResource实例。getConnection方法返回一个 OracleConnection实例。

XA 连接实例返回的 OceanBase Connector/J 连接实例充当物理连接的临时句柄,而不是封装物理连接。物理连接由 XA 连接实例封装。与常规连接完全相同,连接从 XAConnection对象获得连接的行为,直至参与到全局事务为止。这时,自动提交状态设置为 false。全局事务结束后,自动提交状态将返回到其在全局事务之前的值。从 XAConnection获得的连接的默认自动提交状态均为 true

每次调用 XA 连接实例的 getConnection方法时,都会返回一个表现出默认行为的新连接实例,并关闭以前存在的并由同一 XA 连接实例返回的所有以前的连接实例。但是,建议在打开新的连接实例之前显式关闭先前的连接实例。

调用 XA 连接实例的 close方法将关闭与数据库的物理连接,并通常在中间层执行。

XAResource 接口和 Oracle 实施

事务管理器使用 OracleXAResource实例来协调分布式事务的所有事务分支。

每个 OracleXAResource实例都提供给事务管理器调用的关键功能,如下:

  • 将分布式事务与产生此 OracleXAResource实例的 XA 连接实例中运行的事务分支关联和解除关联。本质上,是将分布式事务与 XA 连接实例封装的物理连接或会话相关联。这是通过使用事务 ID 来完成的。

  • 执行分布式事务的两阶段提交功能,以确保在所有事务分支中更改都成功之前,不会在某一个事务分支中提交更改。

注意

  • 因为 XA 连接实例和 OracleXAResource实例之间必须始终存在一对一的关联,所以当关联的 XA 连接实例关闭时,隐式关闭 OracleXAResource实例。
  • 如果事务由指定的 OracleXAResource实例打开,则它也必须由相同的 OracleXAResource实例关闭。

OracleXAResource实例是实现标准 javax.transaction.xa.XAResource接口类的实例。OceanBase Connector/J 使用OracleXAResource类实现 XAResource接口。

每当调用 OracleXAConnection类的 getXAResource方法时, OceanBase Connector/J 都会创建并返回一个 OracleXAResource实例,并且将 OracleXAResource实例与连接实例和通过该连接运行的事务分支相关联。

这种方法是将 OracleXAResource实例与特定连接以及在该连接中运行的事务分支相关联的方式。

OracleXAResource 方法功能和输入参数

OracleXAResource类具有几种方法来协调事务分支和与其关联的分布式事务。此功能通常涉及两阶段提交操作。

从中间层组件(例如应用程序服务器)接收 OracleXAResource实例的事务管理器通常会调用此功能。

这些方法中的每一个都以 Xid实例的形式将事务 ID 作为输入,其中包括事务分支 ID 组件和分布式事务 ID 组件。每个事务分支都有唯一的事务 ID,但是属于同一全局事务的事务分支作为其事务 ID 的一部分,所以具有相同的全局事务组件。

Start

代表事务分支开始工作,将事务分支与分布式事务相关联。语法如下:

void start(Xid xid, int flags)

flags参数必须是以下一个或多个值:

  • XAResource.TMNOFLAGS

    将新事务分支的开始标记为与此 XA 资源实例相关联的会话中的后续操作。该分支将具有事务 ID xid,这是由事务管理器创建的 OracleXid实例。 这会将事务分支映射到适当的分布式事务。

  • XAResource.TMJOIN

    将与此 XA 资源实例相关联会话的后续操作加入到 xid指定的现有事务分支中。

  • XAResource.TMRESUME​恢复 xid 指定的事务分支。

说明

只能恢复之前挂起的事务分支。

  • OracleXAResource.ORATMSERIALIZABLE

    使用事务 ID xid启动可序列化的事务。

  • OracleXAResource.ORATMREADONLY

    使用事务 ID xid启动一个只读事务。

  • OracleXAResource.ORATMREADWRITE

    使用事务 ID xid启动读/写事务。

  • OracleXAResource.ORATRANSLOOSE

    使用事务 ID xid启动一个松散耦合的事务。

TMNOFLAGSTMJOINTMRESUMEORATMSERIALIZABLEORATMREADONLYORATMREADWRITE被定义为 XAResource接口和 OracleXAResource类的 static成员。ORATMSERIALIZABLEORATMREADONLY ORATMREADWRITE是隔离模式标志。默认的隔离行为是 READ COMMITTED

说明

  • 代替使用 TMRESUMEstart方法,事务管理器可以强制转换为 OracleXAResource并使用 resume(Xid xid)方法(Oracle 扩展)。
  • 如果使用 TMRESUME,则还必须使用 TMNOMIGRATE,如 start(xid,XAResource.TMRESUME|OracleXAResource.TMNOMIGRATE)中所示。这可以防止应用程序收到错误信息 ORA 1002: fetch out of sequence
  • 如果错误地使用了隔离模式标识,则会引发代码为 XAER_INVAL的异常。此外,因为无法设置现有事务的隔离级别,所以在恢复全局事务时不能使用隔离模式标识。如果在恢复事务时尝试使用隔离模式标识,则会引发代码为 ORA-24790的外部 Oracle 异常。
  • 为了避免错误 Error ORA 1002: fetch out of sequence,请在启动方法中包括 TMNOMIGRATE标识。例如:start(xid, XAResource.TMSUSPEND | OracleXAResource.TMNOMIGRATE);
  • 在编写使用这些标识的事务管理器时,请注意 OracleXAResource中定义的所有标志都是 Oracle 扩展。

请注意,要在启动事务分支时创建适当的事务 ID,事务管理器必须知道该事务分支属于哪个分布式事务。其机制在中间层和事务管理器之间处理。

End

结束工作代表 xid指定的事务分支,将事务分支与其分布式事务解除关联。语法如下:

void end(Xid xid, int flags)

flags参数可以具有以下值之一:

  • XAResource.TMSUCCESS

    这表明该事务分支已经成功。

  • XAResource.TMFAIL

    这表明该事务分支已失败。

  • XAResource.TMSUSPEND

    这是为了挂起 xid指定的事务分支。通过挂起事务分支,您可以在单个会话中拥有多个事务分支。但是,在给定时间只能激活一个。这比进行两次会话要耗费更多的资源。

TMSUCCESSTMFAILTMSUSPEND被定义为 XAResource接口和 OracleXAResource类的静态成员。

说明

  • 与使用 TMSUSPENDend方法不同,事务管理器可以将其强制转换为 OracleXAResource并使用 suspend(Xid xid)方法(Oracle 扩展)。
  • 暂停事务的 XA 功能提供了一种在单个 JDBC 连接内的各种事务之间进行切换的方法。您可以使用 XA 类来完成此操作。
  • 如果使用 TMSUSPEND,则还必须使用 TMNOMIGRATE,如 end(xid,XAResource.TMSUSPEND| OracleXAResource.TMNOMIGRATE)所示。 这样可以防止应用程序收到错误 ORA 1002: fetch out of sequence
  • 为了避免错误 Error ORA 1002: fetch out of sequence,请将 TMNOMIGRATE标识作为 end方法的一部分。 例如:end(xid, XAResource.TMSUSPEND | OracleXAResource.TMNOMIGRATE);
  • 在编写使用这些标识的事务管理器时,请注意 OracleXAResource中定义的所有标志都是 Oracle 扩展。

Prepare

xid指定的事务分支中准备执行的更改。这是两阶段提交操作的第一阶段,以确保可以访问数据库并且可以成功提交更改。语法如下:

int prepare(Xid xid)

此方法返回一个整数值,如下所示:

  • XAResource.XA_RDONLY

    如果事务分支仅运行只读操作(例如 SELECT语句),则返回此值。

  • XAResource.XA_OK

    如果事务分支运行所有准备就绪且没有错误的更新,则返回此值。

  • NA(不返回任何值)

    如果事务分支运行更新,如果其中任何一个在准备过程中遇到错误,则不返回任何值。在这种情况下,将引发 XA 异常。

XA_RDONLYXA_OK被定义为 XAResource接口和 OracleXAResource类的静态成员。

说明

  • 在调用 prepare方法之前始终在分支上调用 end方法。
  • 如果分布式事务中只有一个事务分支,则无需调用 prepare方法。无需预先准备就可以调用OracleXAResource提交方法。

Commit

xid指定的事务分支中提交准备好的更改。这是两阶段提交的第二阶段,仅在成功准备好所有事务分支之后才执行。语法如下:

void commit(Xid xid, boolean onePhase)

设置 onePhase参数如下:

  • true

    表示在提交事务分支时使用一阶段协议而不是两阶段协议,适用于分布式事务中只有一个事务分支的情况。prepare步骤将被跳过。

  • false

    表示在提交事务分支时使用两阶段协议。

Rollback

xid 指定的事务分支中回滚准备好的更改。语法如下:

void rollback(Xid xid)

Forget

告诉资源管理器忘记启发完成的事务分支。语法如下:

public void forget(Xid xid)

Recover

事务管理器在恢复期间调用此方法,以获取当前处于准备完成或启发完成状态的事务分支的列表。语法如下:

public Xid[] recover(int flag)

说明
TMSTARTRSCANTMENDRSCANTMNOFLAGSflag值会被忽略,其他的 flag值会引发异常。
资源管理器为当前处于准备或启发完成状态的事务分支返回零个或多个 Xid。如果在操作过程中发生错误,则资源管理器将引发适当的 XAException

说明
恢复方法要求在 Oracle 数据库服务器中具有 DBA_PENDING_TRANSACTIONSSELECT权限和 SYS.DBMS_XAEXECUTE权限。

isSameRM

要确定两个 OracleXAResource实例是否对应于同一资源管理器,请从一个 OracleXAResource实例调用 isSameRM方法,并指定另一个 OracleXAResource实例作为输入。

在以下示例中,假定 xares1xares2OracleXAResource实例:

boolean sameRM = is1.isSameRM(is2);

Xid 接口和 Oracle 实施

事务管理器创建事务 ID 实例,并用于协调分布式事务的分支。每个事务分支都分配有唯一的事务 ID,其中包括以下信息:

  • 格式识别码

    格式标识符指定 Java 事务管理器。例如,可能有一个格式标识符 ORCL。该字段不能为空。格式标识符的大小为 4 个字节。

  • 全局事务标识符

    它也被称为分布式事务 ID 组件。全局事务标识符的大小为 64 个字节。

  • 分支限定符

    也称为事务分支 ID 组件。分支限定符的大小为 64 个字节。

属于同一分布式事务的所有事务分支的事务 ID 具有相同的 64 字节全局事务标识符值。但是,总的事务 ID 对于每个事务分支都是唯一的。

XA 事务 ID 实例是实现标准 javax.transaction.xa.Xid接口类的实例,该接口是 X/Open 事务的标识符 XID 的结构的 Java 映射。

Oracle 使用 oracle.jdbc.xa包中的 OracleXid类实现此接口。OracleXid实例仅在事务管理器中使用,对应用程序或应用服务器透明。

说明
Oracle 不需要将 OracleXid用于 OracleXAResource调用。相反,请使用实现 javax.transaction.xa.Xid接口的任何类。

事务管理器在创建 OracleXid实例时可以使用以下内容:

public OracleXid(int fId, byte gId[], byte bId[]) throws XAException

其中,fId是格式标识符的整数值,gId []是全局事务标识符的字节数组,bId []是分支限定符的字节数组。

Xid接口指定以下 getter方法:

  • public int getFormatId()

  • public byte[] getGlobalTransactionId()

  • public type[] getBranchQualifier()