XA interface support
Print
- Last Updated: April 8, 2021
- 3 minute read
- DataDirect Connectors
- ODBC
- Microsoft SQL Server 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 = "ddsqls.dll"; HMODULE sqlsLib = LoadLibrary(libFile); xaSwitch = (XaSwitch)GetProcAddress(sqlsLib, "GetXaSwitch"); #else // Unix handle = dlopen("ddsqls.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("SSWP_XA+HostName=host_name+ PortNumber=1433+ACC=account_credentials+ SesTM=session_timeout+DataSource=dsn_name",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.
- 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.
- dsn_name
- is the data source name.
- 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 a SQL Server 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);