XA in TimesTen
The implementation of XA for TimesTen Classic provides an API that is consistent with the API specified in Distributed Transaction Processing: The XA Specification.
This section describes what you should know when using the TimesTen implementation of XA, covering the following topics:
Introduction to the TimesTen XA Implementation and Limitations
The TimesTen implementation of the XA interfaces is intended for use by transaction managers in distributed transaction processing (DTP) environments. You can use these interfaces to write a new transaction manager or to adapt an existing transaction manager, such as Oracle Tuxedo, to operate with TimesTen resource managers.
In the context of TimesTen XA, the resource managers can be a collection of TimesTen databases, or databases in combination with other commercial databases that support XA.
Note these important limitations:
-
The TimesTen XA implementation does not work with cache. The start of any XA transaction fails if the cache agent is running.
-
You cannot execute an XA transaction if TimesTen replication is enabled.
-
The TimesTen driver manager does not support XA.
-
Do not execute DDL statements within an XA transaction.
TimesTen Database Requirements for XA
To guarantee global transaction consistency, TimesTen XA transaction branches must be durable.
The TimesTen implementation of the xa_prepare()
, xa_rollback()
, and xa_commit()
functions log their actions to the file system, regardless of the value set in the DurableCommits
general connection attribute or by the ttDurableCommit
built-in procedure. (The behavior is equivalent to what occurs with a setting of DurableCommits=1
. See DurableCommits in Oracle TimesTen In-Memory Database
Reference.) If you must recover from a failure, both the resource manager and the TimesTen transaction manager have a consistent view of which transaction branches were active in a prepared state at the time of failure.
Global Transaction Recovery in TimesTen
When a database is loaded from the file system to recover after a failure or unexpected termination, any global transactions that were prepared but not committed are left pending, or in doubt. Regular processing is not enabled until the disposition of all in-doubt transactions has been resolved.
After connection and recovery are complete, TimesTen checks for in-doubt transactions. If there are no in-doubt transactions, operation proceeds as expected. If there are in-doubt transactions, other connections may be created, but virtually all operations are prohibited on those connections until the in-doubt transactions are resolved. Any other ODBC or JDBC calls result in the following error:
Error 11035 - "In-doubt transactions awaiting resolution in recovery must be resolved first"
The list of in-doubt transactions can be retrieved through the XA implementation of
xa_recover()
, then dealt with through the XA call
xa_commit()
, xa_rollback()
, or
xa_forget()
, as appropriate. After all of the in-doubt transactions
are cleared, operation proceeds as expected.
This scheme should be adequate for systems that operate strictly under control of the transaction manager, since the first thing the transaction manager should do after connect is to call xa_recover()
.
If the transaction manager is unavailable or cannot resolve an in-doubt transaction, you can use the ttXactAdmin
utility -HCommit
or -HAbort
option to independently commit or roll back the individual transaction branches. Be aware, however, that these ttXactAdmin
options require ADMIN
privilege. See ttXactAdmin in Oracle TimesTen In-Memory Database
Reference.
Considerations in Using Standard XA Functions With TimesTen
There are some issues concerning the use of standard XA functions in TimesTen, for those creating your own transaction manager.
Discussion covers the following:
xa_open() Function
The xa_info
string used by xa_open()
should
be a connection string identical to that supplied to
SQLDriverConnect
.
"DSN=DataStoreResource;UID=MyName"
XA limits the length of the string to 256 characters. See MAXINFOSIZE
in the xa.h
header file.
The xa_open()
function automatically turns off autocommit when it opens an XA connection.
A connection opened with xa_open()
must be closed with a call to xa_close()
.
Transaction Id (XID) Parameter
XA uniquely identifies global transactions by using a transaction ID, referred to as an XID. The XID is a required parameter for XA functions that manipulate a transaction. Internally, TimesTen maps XIDs to its own transaction identifiers.
The XID defined by the XA standard has some of its members (such as formatID
, gtrid_length
, and bqual_length
) defined as type long
. Historically, this could cause problems when a 32-bit client application connected to a 64-bit server, or a 64-bit client application connected to a 32-bit server, because long
is a 32-bit integer on 32-bit platforms and a 64-bit integer on 64-bit platforms (other than 64-bit Windows). Because of this, TimesTen internally uses only the 32 least significant bits of those XID members regardless of the platform type of client or server. TimesTen does not support any value in those XID members that does not fit in a 32-bit integer.
TimesTen tt_xa_context Function to Obtain ODBC Handle From XA Connection
The TimesTen function tt_xa_context()
enables you to acquire the ODBC connection handle associated with an XA connection opened by xa_open()
.
tt_xa_context Syntax and Parameter Descriptions
Syntax for the tt_xa_context
function is as follows:
#include <tt_xa.h>
int tt_xa_context(int* rmid, SQLHENV* henv, SQLHDBC* hdbc);
This table describes the parameters:
Parameter | Type | Description |
---|---|---|
|
|
The specified resource manager ID If this is non-null, the function returns the handles associated with the If the specified |
|
|
The environment handle associated with the current |
|
|
The connection handle associated with the current |
The function returns these values:
0: Success
1: rmid
not found
-1: Invalid parameter
Using tt_xa_context
This section shows how to use tt_xa_context
.
In the following example, assume Tuxedo has used xa_open()
and xa_start()
to open a connection to the database and start a transaction. To do further ODBC processing on the connection, use the tt_xa_context()
function to locate the SQLHENV
and SQLHDBC
handles allocated by xa_open()
.
do_insert() { SQLHENV henv; SQLHDBC hdbc; SQLHSTMT hstmt; /* retrieve the handles for the current connection */ tt_xa_context(NULL, &henv, &hdbc); /* now we can do our ODBC programming as usual */ SQLAllocStmt(hdbc, &hstmt); SQLExecDirect(hstmt, "insert into t1 values (1)", SQL_NTS); SQLFreeStmt(hstmt, SQL_DROP); }
Considerations in Calling ODBC Functions Over XA Connections in TimesTen
There are factors to consider when calling ODBC functions using an ODBC handle associated with an XA connection opened by xa_open()
.
These are discussed in the following sections:
Autocommit
To simplify operation and prevent possible contradictions, xa_open()
automatically turns off autocommit when it opens an XA connection.
Autocommit may subsequently be turned on or off during local transaction work, but must be turned off before xa_start()
is called to begin work on a global transaction branch. If autocommit is on, a call to xa_start()
returns the following error:
Error 11030 - "Autocommit must be turned off when working on global (XA) transactions"
Once xa_start()
has been called to begin work on a global transaction branch, autocommit may not be turned on until such work has been completed through a call to xa_end()
. Any attempt to turn on autocommit in this case results in the same error as above.
Local Transaction COMMIT and ROLLBACK
Once work on a global transaction branch has commenced through a call to xa_start()
, attempts to perform a local commit or rollback using SQLTransact
results in an error.
Error 11031 - "Invalid combination of local transaction and global (XA) transaction"
XA Resource Manager Switch
This section discusses the XA resource manager switch.
About the Resource Manager Switch
Each resource manager defines a switch in its xa.h
header file that
provides the transaction manager with access to the XA functions in the resource managers.
The transaction manager never directly calls an XA interface function. Instead, it calls the function in the switch table that, in turn, points to the appropriate function in the resource manager. Then resource managers can be added and removed without the requirement to recompile the applications.
In the TimesTen implementation of XA, the functions in the XA switch, xa_switch_t
, point to their respective functions defined in a TimesTen switch, tt_xa_switch
.
XA Switch xa_switch_t
The xa_switch_t
structure is defined by the XA
specification.
/* XA Switch Data Structure */ #define RMNAMESZ 32 /* length of resource manager name, */ /* including the null terminator */ #define MAXINFOSIZE 256 /* maximum size in bytes of xa_info strings, */ /* including the null terminator */ struct xa_switch_t { char name[RMNAMESZ]; /* name of resource manager */ long flags; /* resource manager specific options */ long version; /* must be 0 */ int (*xa_open_entry)(char*, int, long); /* xa_open function pointer */ int (*xa_close_entry)(char*, int, long); /* xa_close function pointer*/ int (*xa_start_entry)(XID*, int, long); /* xa_start function pointer */ int (*xa_end_entry)(XID*, int, long); /* xa_end function pointer */ int (*xa_rollback_entry)(XID*, int, long); /* xa_rollback function pointer */ int (*xa_prepare_entry)(XID*, int, long); /* xa_prepare function pointer */ int (*xa_commit_entry)(XID*, int, long); /* xa_commit function pointer */ int (*xa_recover_entry)(XID*, long, int, long); /* xa_recover function pointer*/ int (*xa_forget_entry)(XID*, int, long); /* xa_forget function pointer */ int (*xa_complete_entry)(int*, int*, int, long);/* xa_complete function pointer */ }; typedef struct xa_switch_t xa_switch_t; /* * Flag definitions for the RM switch */ #define TMNOFLAGS 0x00000000L /* no resource manager features selected */ #define TMREGISTER 0x00000001L /* resource manager dynamically registers */ #define TMNOMIGRATE 0x00000002L /* RM does not support association migration */ #define TMUSEASYNC 0x00000004L /* RM supports asynchronous operations */
TimesTen Switch tt_xa_switch
The tt_xa_switch
names the actual functions implemented by a TimesTen resource manager. It also indicates explicitly that association migration is not supported. In addition, dynamic registration and asynchronous operations are not supported.
struct xa_switch_t tt_xa_switch = { "TimesTen", /* name of resource manager */ TMNOMIGRATE, /* RM does not support association migration */ 0, tt_xa_open, tt_xa_close, tt_xa_start, tt_xa_end, tt_xa_rollback, tt_xa_prepare, tt_xa_commit, tt_xa_recover, tt_xa_forget, tt_xa_complete };
XA Error Handling in TimesTen
The XA specification has a limited and strictly defined set of errors that can be
returned from XA interface calls. The ODBC SQLError
function returns
XA-defined errors along with any additional information.
The TimesTen XA-related errors begin at number 11000. Errors 11002 through 11020 correspond to the errors defined by the XA standard.
See Errors and Warnings in Oracle TimesTen In-Memory Database Error Messages and SNMP Traps.