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().

xa_close() Function

The xa_info string used by xa_close() should be empty.

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

rmid

int

The specified resource manager ID

If this is non-null, the function returns the handles associated with the rmid value.

If the specified rmid is null, the function returns the handles associated with the first connection on this thread. For example, specify a null value if the connection has been opened outside the scope of the user-written code, where rmid is unknown. This establishes context in the application environment.

henv

out SQLHENV

The environment handle associated with the current xa_open() context

hdbc

out SQLHDBC

The connection handle associated with the current xa_open() context

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"

Close Open Cursors

Any open statement cursors must be closed using SQLFreeStmt with a value of SQL_CLOSE before calling xa_end() to end work on a global transaction branch.

Otherwise, the following error is returned:

Error 11032 - "XA request failed due to open cursors"

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.