XA interface support
Print
- Last Updated: April 8, 2021
- 3 minute read
- DataDirect Connectors
- ODBC
- Oracle Database Wire Protocol 8.0
- Documentation
The driver enables support for distributed transactions by implementing the XA interface. In an X/Open Distributed Transaction Processing (DTP) system, the XA interface provides a method for the Transaction Manager (TM) to call xa_ routines to interact with the Resource Manager (RM).
For more information on the X/Open DTP system, the XA interface, and the XA components discussed in the following procedure, refer to Distributed Transaction Processing: The XA Specification.
To perform distributed transactions:
-
Establish a connection between your application and the RM (the
database server you want to connect to) in AUTOCOMMIT_OFF mode. For example:
rc = SQLConnect((HDBC)hdbc, (SQLCHAR*)dataSource, SQL_NTS, (SQLWCHAR*)"user", SQL_NTS, (SQLWCHAR*)"password", SQL_NTS); rc = SQLSetConnectAttr((HDBC)hdbc, SQL_ATTR_AUTOCOMMIT, SQL_AUTOCOMMIT_OFF, SQL_NTS);where:
- user
- is the user name required to connect to the RM.
- password
- is the password required to connect to the RM.
-
Load the driver library and call the
GetXaSwitch()function.GetXaSwitch()returns the XA switch data structure (xa_switch_t) exposed by the RM.xa_switch_tcontains function pointers to thexa_routines that must be invoked by the TM to interact with the RM. For example:#ifndef WIN32 LPCSTR libFile = "ddora28.dll"; HMODULE oraLib = LoadLibrary(libFile); xaSwitch = (XaSwitch)GetProcAddress(oraLib, "GetXaSwitch"); #else // Unix handle = dlopen("ddora28.so", RTLD_LAZY); xaSwitch = (XaSwitch)dlsym(handle, "GetXaSwitch_"); #endif // End of WIN32 xaSwitch(0, &xaSwitchPtr); -
Establish an XA connection between TM and RM. As a result, a global
transaction is created. For example:
int RMID = rmid_value; // Use xa_open_entry with XA connection string, RMID, and flag to establish the connection. rc = xaSwitchPtr->xa_open_entry("Oracle_XA+HostName=host_name+ PortNumber=1521+Sid=sid_value+ACC=account_credentials+ SesTM=session_timeout+LogDir=log_dir_path",rmid,flag);where:
- rmid_value
- is the RM identifier.
- host_name
- is the name or IP address of the RM you want to connect to.
- sid_value
- is the system identifier that refers to the instance of Oracle running on the server.
- account_credentials
- are the credentials required to connect to the RM. They must be
provided in the following format:
P/USER/PASSWORD.
- session_timeout
- is the number of seconds the session remains active.
- log_dir_path
- is the path to the directory where log files are stored.
- flag
- determines the function that is called after the connection
ends. For example,
TMASYNCandTMNOFLAGS.
-
Create an XID for the transaction branch you want to associate with
the global transaction. For example:
void DoMakeXid(int id, XID *xaXid){ int *dataPtr; memset(xaXid, 0, sizeof(*xaXid)); xaXid->formatID = format_id xaXid->gtrid_length = gtrid_length; xaXid->bqual_length = bqual_length; dataPtr = (int*)&xaXid->data; dataPtr[0] = GetCurrentThreadId(); dataPtr[1] = GetCurrentThreadId(); }where:
- format_id
- is the identifier that indicates the naming convention used by the TM.
- gtrid_length
- is the length of the global transaction ID. It should not exceed 64 bytes.
- bqual_length
- is the length of the branch qualifier ID. It should not exceed 64 bytes.
Note: In the above example, the GetCurrentThreadId() function returns the global transaction and branch qualifier IDs. However, if you are using an Oracle TM, you can use the IDs obtained from the TM instead of those returned by the GetCurrentThreadId() function. -
Start the transaction branch, enlist the connection, and then execute
the required query.
// Use xa_start_entry to start the transaction branch. rc = xaSwitchPtr->xa_start_entry(&xId, rmid, flag); // Enlist connection. rc = SQLSetConnectOption(hDbc, SQL_ATTR_ENLIST_IN_XA, (UDWORD)1); // Execute query. rc = SQLExecDirect(hstmt, (unsigned char*)"INSERT INTO table_name VALUES(value_1, 'value_2')", SQL_NTS); -
Prepare and commit the transaction branch; then, delist the
connection.
// Use xa_prepare_entry to prepare the trasaction branch. rc = xaSwitchPtr->xa_prepare_entry(&xId, rmid, TMNOFLAGS); // Use xa_commit_entry to commit the transaction branch. rc = xaSwitchPtr->xa_commit_entry(&xId, rmid, TMNOFLAGS); // Delist connection. rc = SQLSetConnectOption(hDbc, SQL_ATTR_ENLIST_IN_XA, (UDWORD)0); -
End the transaction branch.
// Use xa_end_entry to end the transaction branch. rc = xaSwitchPtr->xa_end_entry(&xId, rmid, flag);