XA components are the standard XA interfaces specified for OceanBase Connector/J.
XADatasource interface and Oracle implementation
The javax.sql.XADataSource interface outlines the standard features of XA data sources. The getXAConnection method reloads and returns an XA connection instance and allows you to use the username and password as the input. Here is an example:
public interface XADataSource
{
XAConnection getXAConnection() throws SQLException;
XAConnection getXAConnection(String user, String password)
throws SQLException;
...
}
OceanBase Connector/J uses the OracleXADataSource class to implement the XADataSource interface. The OracleXADataSource class extends the OracleConnectionPoolDataSource class, and the OracleConnectionPoolDataSource class extends the OracleDataSource class. Therefore, OceanBase Connector/J includes all connection attributes.
The getXAConnection method of the OracleXADataSource class returns the Oracle implementation of XA connection instances, which are OracleXAConnection instances.
Note
You can register XA data sources with Java Naming and Directory Interface (JNDI) by using naming conventions same as those for non-pooled data sources mentioned earlier.
XAConnection interface and Oracle implementation
An XA connection instance, like a pooled connection instance, is encapsulated with a physical connection to the database. The database here refers to the database specified in the connection attributes of the XA data source instance that generates the XA connection instance.
Each XA connection instance can also generate an OracleXAResource instance, which corresponds to the XA connection instance and is used to coordinate distributed transactions.
An XA connection instance is an instance that implements a standard javax.sql.XAConnection interface class. Here is an example:
public interface XAConnection extends PooledConnection
{
javax.jta.xa.XAResource getXAResource() throws SQLException;
}
The XAConnection interface extends the javax.sql.PooledConnection interface, and therefore includes the getConnection, close, addConnectionEventListener, and removeConnectionEventListener methods.
OceanBase Connector/J uses the OracleXAConnection class to implement the XAConnection interface. The OracleXAConnection class also extends the OraclePooledConnection class.
The getXAResource method of the OracleXAConnection class returns the Oracle implementation of an OracleXAResource instance. The getConnection method returns an OracleConnection instance.
The OceanBase Connector/J instance returned by the XA connection instance serves as a temporary handle of the physical connection, rather than encapsulating the physical connection. The physical connection is encapsulated by the XA connection instance. Same as a regular connection, an XA connection obtains the connection behavior from the XAConnection object until it participates in a global transaction. At this point, the auto commit state is set to false. After the global transaction ends, the auto commit state will be reset to its original value before the global transaction. The default auto commit state of the connection obtained from the XAConnection interface is true.
Each time you call the getConnection method of the XA connection instance, a new connection instance that exhibits the default behavior is returned, and all previous connection instances returned by the same XA connection instance are closed. However, we recommend that you explicitly close previous connection instances before you open a new connection instance.
The close method of the XA connection instance closes the physical connection to the database and is usually executed in the intermediate layer.
XAResource interface and Oracle implementation
The transaction manager uses the OracleXAResource instance to coordinate all the transaction branches of a distributed transaction.
Each OracleXAResource instance provides the following key features to the transaction manager:
Associates and de-associates a distributed transaction and the transaction branches running in the XA connection instance that generates the
OracleXAResourceinstance. In essence, this feature associates the distributed transaction with physical connections or sessions encapsulated in the XA connection instance. This feature is implemented based on the transaction ID.Performs two-phase commit for a distributed transaction. This feature ensures that changes are not committed in a transaction branch before changes are applied to all transaction branches.
Notice
- The
OracleXAResourceinstance must be implicitly closed when the associated XA connection instance is closed, because the XA connection instance and theOracleXAResourceinstance must always be in one-to-one association. - A transaction must be closed by using an
OracleXAResourceinstance same as theOracleXAResourceinstance specified for starting the transaction.
- The
An OracleXAResource instance is an instance that implements the standard javax.transaction.xa.XAResource interface class. OceanBase Connector/J uses the OracleXAResource class to implement the XAResource interface.
Each time the getXAResource method of the OracleXAConnection class is called, OceanBase Connector/J creates and returns an OracleXAResource instance, and associates the OracleXAResource instance with a connection instance and with transaction branches that run in the connection.
This method associates the OracleXAResource instance with a specific connection and transaction branches that run in the connection.
OracleXAResource method features and input parameters
The OracleXAResource class has several methods for coordinating transaction branches and the distributed transactions associated with the transaction branches. This feature typically involves a two-phase commit operation.
The transaction manager that receives the OracleXAResource instance from an intermediate-layer component, such as an application server, usually calls this feature.
Each of these methods uses a transaction ID as input in the form of an Xid instance, which includes a transaction branch ID component and a distributed transaction ID component. Each transaction branch has a unique transaction ID. Transaction branches that belong to the same global transaction share the same distributed transaction ID component.
Start
This method enables a transaction branch to work and associate it with the distributed transaction. The syntax is as follows:
void start(Xid xid, int flags)
The flags parameter must be set to one or more of the following values:
XAResource.TMNOFLAGSMarks the start of a new transaction branch as for subsequent operations in the session that is associated with this XA resource instance. The branch will have a transaction ID
xid, which is anOracleXidinstance created by the transaction manager. This operation maps the transaction branch to the corresponding distributed transaction.XAResource.TMJOINJoins the subsequent operations in the session that is associated with this XA resource instance to the transaction branch specified by
xid.XAResource.TMRESUMEResumes the transaction branch specified by
xid.Note
Only previously suspended transaction branches can be resumed.
XAResource.ORATMSERIALIZABLEUses the transaction ID specified by
xidto start a serializable transaction.XAResource.ORATMREADONLYUses the transaction ID specified by
xidto start a read-only transaction.XAResource.ORATRANSLOOSEUses the transaction ID specified by
xidto start a loosely coupled transaction.
TMNOFLAGS, TMJOIN, TMRESUME, ORATMSERIALIZABLE, and ORATMREADONLY are defined as static members of the XAResource interfaces and static members of the OracleXAResource class. ORATMSERIALIZABLE and ORATMREADONLY are isolation mode flags. The default isolation behavior is READ COMMITTED.
Note
- As an alternative of the
startmethod ofTMRESUME, the transaction manager can be forcibly switched to useOracleXAResourceand theresume(Xid xid)method, which is an Oracle extension. - If you use
TMRESUME, you must also useTMNOMIGRATE, for example,start(xid,XAResource.TMRESUME|OracleXAResource.TMNOMIGRATE). This prevents theORA 1002: fetch out of sequenceerror for the application. - If the isolation mode flag is incorrectly used, an exception with the error code
XAER_INVALis returned. In addition, the isolation level cannot be set for existing transactions. Therefore, you cannot use the isolation mode flag during restoration of global transactions. If you try to use the isolation mode flag during restoration of a transaction, an exception with the error codeORA-24790is returned. - To avoid the
Error ORA 1002: fetch out of sequenceerror, include theTMNOMIGRATEflag in the start method, for example,start(xid, XAResource.TMSUSPEND | OracleXAResource.TMNOMIGRATE);. - When you compile a transaction manager that uses these flags, note that all flags defined in
OracleXAResourceare Oracle extensions.
Note that, to create an appropriate transaction ID when a transaction branch is started, the transaction manager must know the distributed transaction that the transaction branch belongs to. The mechanism is implemented between the intermediate layer and the transaction manager.
End
This method closes the transaction branch specified by xid, that is, disassociates the transaction branch from its distributed transaction. The syntax is as follows:
void end(Xid xid, int flags)
The flags parameter can have one of the following values:
XAResource.TMSUCCESSIndicates the transaction branch has succeeded.
XAResource.TMFAILIndicates that the transaction branch has failed.
XAResource.TMSUSPENDSuspends the transaction branch specified by
xid. By suspending a transaction branch, you can have multiple transaction branches in a single session. However, only one transaction branch can be activated at a given time. This method consumes more resources than when two sessions are run.
TMSUCCESS, TMFAIL, and TMSUSPEND are defined as static members of the XAResource interface and static members of the OracleXAResource class.
Note
- Different from using the
endmethod ofTMSUSPEND, the transaction manager can forcibly convert it toOracleXAResourceand use thesuspend(Xid xid)method, which is an Oracle extension. - The XA feature for suspending transactions provides a way to switch between various transactions within a single JDBC connection. You can use an XA class to complete the operation.
- If you use
TMSUSPEND, you must also useTMNOMIGRATE, for example,end(xid,XAResource.TMSUSPEND| OracleXAResource.TMNOMIGRATE). This prevents theORA 1002: fetch out of sequenceerror for the application. - To avoid the
Error ORA 1002: fetch out of sequenceerror, include theTMNOMIGRATEflag in theendmethod, for example,end(xid, XAResource.TMSUSPEND | OracleXAResource.TMNOMIGRATE);. - When you compile a transaction manager that uses these flags, note that all flags defined in
OracleXAResourceare Oracle extensions.
Prepare
This method prepares the changes to be executed in the transaction branch specified by xid. This is the first phase of a two-phase commit operation and ensures that the database can be accessed and changes can be committed. The syntax is as follows:
int prepare(Xid xid)
This method returns an integer value.
XAResource.XA_RDONLYIf the transaction branch runs only read-only operations, for example, a
SELECTstatement, this value is returned.XAResource.XA_OKIf the transaction branch runs all prepared updates that have no errors, this value is returned.
NA (no value returned)
If any one of the updates to be run by the transaction branch encounters an error during preparation, no value is returned. In this case, an XA exception will be thrown.
XA_RDONLY and XA_OK are defined as static members of the XAResource interface and static members of the OracleXAResource class.
Note
- Always call the
endmethod on the branch before you call thepreparemethod. - If a distributed transaction has only one branch, you do not need to call the
preparemethod. You can directly call the commit method forOracleXAResource.
Commit
This method commits the prepared changes in the transaction branch specified by xid. This is the second phase of a two-phase commit operation and is executed only after all transaction branches have been prepared. The syntax is as follows:
void commit(Xid xid, boolean onePhase)
Set the onePhase parameter to either of the following values:
trueThis value specifies that a one-phase protocol, instead of a two-phase protocol, is used when a transaction branch is committed. This method is applicable when the distributed transaction has only one transaction branch. In this case, the
preparestep will be skipped.falseThis value specifies that the two-phase protocol is used when a transaction branch is committed.
Rollback
This method rolls back the prepared changes in the transaction branch specified by xid. The syntax is as follows:
void rollback(Xid xid)
Forget
This method tells the resource manager to forget about the transaction branch that has been heuristically completed. The syntax is as follows:
public void forget(Xid xid)
Recover
The transaction manager calls this method during recovery to get a list of transaction branches that are ready or heuristically completed. The syntax is as follows:
public Xid[] recover(int flag)
Note
The flag values of TMSTARTRSCAN, TMENDRSCAN, and TMNOFLAGS will be ignored and other flag values will cause an exception.
The resource manager returns zero or more Xid values for transaction branches that are in the prepared or heuristically completed state. If an error occurs during the operation, the resource manager returns the appropriate XAException.
Note
To use the recovery method, you must have the SELECT privilege on DBA_PENDING_TRANSACTIONS and the EXECUTE privilege on SYS.DBMS_XA in the OBServer node.
isSameRM
To determine whether two OracleXAResource instances belong to the same resource manager, call the isSameRM method from one OracleXAResource instance, and specify another OracleXAResource instance as input.
In the following example, it is assumed that xares1 and xares2 are OracleXAResource instances:
boolean sameRM = is1.isSameRM(is2);
Xid interface and Oracle implementation
The transaction manager creates transaction ID instances to coordinate the branches of a distributed transaction. Each transaction branch is assigned a unique transaction ID, which includes the following information:
Format identifier
The format identifier specifies the Java transaction manager. For example, a format identifier
ORCLmay be included. This field must be specified. The size of a format identifier is 4 bytes.Global transaction ID
It is also called the distributed transaction ID component. The size of a global transaction ID is 64 bytes.
Branch qualifier
It is also known as the transaction branch ID component. The size of a branch qualifier is 64 bytes.
The transaction IDs of all transaction branches of the same distributed transaction have the same 64-byte global transaction ID. However, the transaction ID of each transaction branch is unique.
The XA transaction ID instance is an instance that implements the standard javax.transaction.xa.Xid interface class, which is a Java mapping of the structure of the X/Open transaction identifier (XID).
OceanBase Database uses the OracleXid class in the oracle.jdbc.xa package to implement this interface. OracleXid instances are used only in the transaction manager and are transparent to the application or application server.
Note
OceanBase Database does not use OracleXid to call OracleXAResource. Instead, use any class that implements the javax.transaction.xa.Xid interface.
The transaction manager can use the following content when it creates an OracleXid instance:
public OracleXid(int fId, byte gId[], byte bId[]) throws XAException
fId is the format identifier in the format of an integer. gId [] is the global transaction ID, and bId [] is the branch qualifier, both of which are arrays of bytes.
The Xid interface specifies the following getter methods:
public int getFormatId()public byte[] getGlobalTransactionId()public type[] getBranchQualifier()