This chapter describes the TimesTen implementation of the X/Open XA standard.
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.
The purpose of this chapter is to provide information specific to the TimesTen implementation of XA and is intended to be used with the following documents:
X/Open CAE Specification, Distributed Transaction Processing: The XA Specification published by the The Open Group (http://www.opengroup.org
).
Tuxedo documentation, available through the following location:
http://www.oracle.com/technetwork/middleware/weblogic/documentation
This chapter includes the following topics:
Important:
The TimesTen XA implementation does not work with IMDB Cache. The start of any XA transaction will fail if the cache agent is running.
You cannot execute an XA transaction if replication is enabled.
Do not execute DDL statements within an XA transaction.
This section provides a brief overview of the following XA concepts:
Figure 6-1 that follows illustrates the interfaces defined by the X/Open DTP model.
Figure 6-1 Distributed transaction processing model
The TX interface is what applications use to communicate with a transaction manager. The figure shows an application communicating global transactions to the transaction manager. In the DTP model, the transaction manager breaks each global transaction down into multiple branches and distributes them to separate resource managers for service. It uses the XA interface to coordinate each transaction branch with the appropriate resource manager.
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.
Global transaction control provided by the TX and XA interfaces is distinct from local transaction control provided by the native ODBC interface. It is generally best to maintain separate connections for local and global transactions. Applications can obtain a connection handle to a TimesTen resource manager in order to initiate both local and global transactions over the same connection. See "TimesTen tt_xa_context function to obtain ODBC handle from XA connection" for more information.
In an XA implementation, the transaction manager commits the distributed branches of a global transaction by using a two-phase commit protocol.
In phase one, the transaction manager directs each resource manager to prepare to commit, which is to verify and guarantee it can commit its respective branch of the global transaction. If a resource manager cannot commit its branch, the transaction manager rolls back the entire transaction in phase two.
In phase two, the transaction manager either directs each resource manager to commit its branch or, if a resource manager reported it was unable to commit in phase one, rolls back the global transaction.
Note the following optimizations:
If a global transaction is determined by the transaction manager to have involved only one branch, it skips phase one and commits the transaction in phase two.
If a global transaction branch is read-only, where it does not generate any transaction log records, the transaction manager commits the branch in phase one and skips phase two for that branch.
Note:
The transaction manager considers the global transaction committed if and only if all branches successfully commit.The TimesTen implementation of XA 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:
TimesTen tt_xa_context function to obtain ODBC handle from XA connection
Considerations in calling ODBC functions over XA connections in TimesTen
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 disk, 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 for related information.) 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.
Rollback of transactions requires transaction logging, which is always enabled with XA.
When a database is loaded from disk to recover after a failure or unexpected termination, any global transactions that were prepared but not committed are left pending, or in doubt. Normal 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 normal. 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 normally.
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 to independently commit or abort the individual transaction branches. Be aware, however, that these ttXactAdmin
options require ADMIN
privilege. See "ttXactAdmin" in Oracle TimesTen In-Memory Database Reference.
This section describes some issues concerning the use of TimesTen XA functions, which are of interest if you are writing your own transaction manager.
The xa_info
string used by xa_open()
should be a connection string identical to that supplied to SQLDriverConnect
, such as:
"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()
.
Note:
Privilege to connect to the database must be explicitly granted to every user other than the instance administrator, through theCREATE SESSION
privilege. Refer to "Access control for connections".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
. Be aware that this can cause problems when 32-bit client applications connect to a 64-bit server, or 64-bit client applications connect to a 32-bit server. This is because long
is a 32-bit integer on 32-bit platforms but a 64-bit integer on 64-bit platforms, other than 64-bit Windows. Hence, 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 provides the function tt_xa_context()
, which enables you to acquire the ODBC connection handle associated with an XA connection opened by xa_open()
.
#include <tt_xa.h> int tt_xa_context(int* rmid, SQLHENV* henv, SQLHDBC* hdbc);
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 |
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. |
0: Success
1: rmid
not found
-1: Invalid parameter
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()
.
Example 6-1 Using tt_xa_context() to locate handles
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); }
This section describes some TimesTen issues to be aware of when calling ODBC functions using an ODBC handle associated with an XA connection opened by xa_open()
.
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 will result in the same error as above.
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 the following error:
Error 11031- "Illegal combination of local transaction and global (XA) transaction"
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, which, in turn, points to the appropriate function in the resource manager. This allows resource managers to 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
.
The xa_switch_t
structure defined by the XA specification is as follows:
/* * 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 */
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 };
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 "Warnings and Errors" in Oracle TimesTen In-Memory Database Error Messages and SNMP Traps for the complete list of errors.
This section discusses issues and procedures for using XA with the Windows ODBC driver manager. (UNIX ODBC driver managers are not considered.)
XA support through the ODBC driver manager requires special handling. There are two fundamental problems:
The XA interface is not part of the defined ODBC interface. If the XA symbols are directly referenced in an application, it is not possible to link with only the driver manager library to resolve all the external references.
By design, the driver manager determines which driver .dll
file to load at connect time, when you call SQLConnect
or SQLDriverConnect
. XA dictates that the connection should be opened through xa_open()
. However, the correct xa_open()
entry point cannot be located until the .dll
is loaded during the connect operation itself.
Note that the driver manager objective of database portability is generally not applicable here, since each XA implementation is essentially proprietary. The primary benefit of driver manager support for XA-enabled applications is to allow TimesTen-specific applications to run transparently with either the TimesTen direct driver or the TimesTen Client/Server driver.
On Windows installations, TimesTen provides a driver manager extension library, ttxadm1121.dll
, for XA functions. Applications can make XA calls directly, but must link in the extension library.
To link with the ttxadm1121.dll
library, applications must include ttxadm1121.lib
before odbc32.lib
in their link line. For example:
# Link with the ODBC driver manager appldm.exe:appl.obj $(CC) /Feappldm.exe appl.obj ttxadm1121.lib odbc32.lib
Note:
The XA driver manager extension is implemented only for 32-bit Windows applications.To configure Tuxedo to use the TimesTen resource managers, perform the following tasks.
Important:
Though TimesTen XA has been demonstrated to work with the Oracle Tuxedo transaction manager, TimesTen cannot guarantee the operation of DTP software beyond the TimesTen implementation of XA.Notes:
The examples in this section use the direct driver. You can also use the client/server library or driver manager library with the XA extension library.
Information on configuring TimesTen for object-relational mapping frameworks and application servers, including Oracle WebLogic Application Server, is available in the TimesTen Quick Start. Click J2EE App Servers under Configuration and Setup.
To integrate the TimesTen XA resource manager into the Oracle Tuxedo system, update the $TUXDIR/udataobj/RM
file to identify the TimesTen resource manager, the name of the TimesTen resource manager switch (tt_xa_switch
), and the name of the library for the resource manager.
On UNIX platforms, add the following:
TimesTen:tt_xa_switch:-Linstall_dir/lib -ltten
For example:
TimesTen:tt_xa_switch:-L/opt/TimesTen/giraffe/lib -ltten
On Windows platforms, add the following:
TimesTen;tt_xa_switch;install_dir\lib\ttdv1121.lib
For example:
TimesTen;tt_xa_switch;C:\TimesTen\giraffe\lib\ttdv1121.lib
Note:
Theinstall_dir
is the path to the TimesTen home directory.Use the buildtms
command to build a transaction manager server for the TimesTen resource manager. Then copy the TMS_TT
file created by buildtms
to the $TUXDIR/bin
directory.
On UNIX platforms, the commands are the following:
buildtms -o TMS_TT -r TimesTen -v cp TMS_TT $TUXDIR/bin
On Windows platforms, the commands are the following:
buildtms -o TMS_TT -r TimesTen -v copy TMS_TT.exe %TUXDIR%\bin
For TMSNAME
, specify the TMS_TT
file created by the buildtms
command described in the preceding section.
TMSNAME=TMS_TT
Enter a line for each TimesTen resource manager that includes a group name, followed by the LMID
, GRPNO
, and OPENINFO
parameters. Your OPENINFO
string should look like this:
OPENINFO="TimesTen:DSN=DSNname"
Where DSNname
is the name of the database.
Note that on Windows, Tuxedo servers run as user SYSTEM
. Add the UID
general connection attribute to the OPENINFO
string to specify a user other than SYSTEM
for the connection:
OPENINFO="TimesTen:DSN=DSNname;UID=user"
Do not specify a CLOSEINFO
parameter for any TimesTen resource manager.
Example 6-2 shows the portions of a UBBCONFIG
file used to configure two TimesTen resource managers, GROUP1
and GROUP2
.
Example 6-2 Configuring TimesTen resource managers
*RESOURCES ... *MACHINES ... ENGSERV LMID=simple *GROUPS DEFAULT: TMSNAME=TMS_TT TMSCOUNT=2 GROUP1 LMID=simple GRPNO=1 OPENINFO="TimesTen:DSN=MyDSN1;UID=MyName" GROUP2 LMID=simple GRPNO=2 OPENINFO="TimesTen:DSN=MyDSN2;UID=MyName" *SERVERS DEFAULT: CLOPT="-A" simpserv1 SRVGRP=GROUP1 SRVID=1 simpserv2 SRVGRP=GROUP2 SRVID=2 *SERVICES TOUPPER TOLOWER
Set the CFLAGS
environment variable to include the install_dir
/include
directory that holds the TimesTen header files. Then use the buildserver
command to construct an Oracle Tuxedo ATMI server load module.
On UNIX platforms, enter the following.
export CFLAGS=-Iinstall_dir/include
buildserver -o server -f server.c -r TimesTen -s SERVICE
On Windows platforms, enter the following.
set CFLAGS=-Iinstall_dir\Include
buildserver -o server -f server.c -r TimesTen -s SERVICE
Note:
Theinstall_dir
is the path to the TimesTen home directory.Example 6-3 shows an example of how to use the buildclient
command to construct the client module (simpcl
) and the buildserver
command to construct the two server modules described in the UBBCONFIG
file in Example 6-2 above.