Chapter 14. Transactions

Data Virtualization provides three types of transactions from a client perspective:

  1. Global
  2. Local
  3. Request Level

All are implemented by Data Virtualization logically as XA transactions. See the JTA specification for more on XA Transactions.

14.1. Local Transactions

A Local transaction from a client perspective affects only a single resource, but can coordinate multiple statements.

14.1.1. JDBC Specific

The Connection class uses the autoCommit flag to explicitly control local transactions. By default, autoCommit is set to true, which indicates request level or implicit transaction control.

An example of how to use local transactions by setting the autoCommit flag to false.

Local transaction control using autoCommit

// Set auto commit to false and start a transaction
connection.setAutoCommit(false);

try {
    // Execute multiple updates
    Statement statement = connection.createStatement();
    statement.executeUpdate("INSERT INTO Accounts (ID, Name) VALUES (10, 'Mike')");
    statement.executeUpdate("INSERT INTO Accounts (ID, Name) VALUES (15, 'John')");
    statement.close();

    // Commit the transaction
    connection.commit();

} catch(SQLException e) {
    // If an error occurs, rollback the transaction
    connection.rollback();
}

This example demonstrates several things:

  1. Setting autoCommit flag to false. This will start a transaction bound to the connection.
  2. Executing multiple updates within the context of the transaction.
  3. When the statements are complete, the transaction is committed by calling commit().
  4. If an error occurs, the transaction is rolled back using the rollback() method.

Any of the following operations will end a local transaction:

  1. Connection.setAutoCommit(true) – if previously set to false
  2. Connection.commit()
  3. Connection.rollback()
  4. A transaction will be rolled back automatically if it times out.

14.1.1.1. Turning Off JDBC Local Transaction Controls

In some cases, tools or frameworks above Data Virtualization will call setAutoCommit(false), commit() and rollback() even when all access is read-only and no transactions are necessary. In the scope of a local transaction Data Virtualization will start and attempt to commit an XA transaction, possibly complicating configuration or causing performance degradation.

In these cases, you can override the default JDBC behavior to indicate that these methods should perform no action regardless of the commands being executed. To turn off the use of local transactions, add this property to the JDBC connection URL

disableLocalTxn=true
Tip

Turning off local transactions can be dangerous and can result in inconsistent results (if reading data) or inconsistent data in data stores (if writing data). For safety, this mode should be used only if you are certain that the calling application does not need local transactions.

14.1.2. Transaction Statements

Transaction control statements, which are also applicable to ODBC clients, explicitly control the local transaction boundaries. The relevant statements are:

  • START TRANSACTION- synonym for connection.setAutoCommit(false)
  • COMMIT- synonym for connection.setAutoCommit(true)
  • ROLLBACK- synonym for connection.rollback() and returning to auto commit mode.

14.2. Request Level Transactions

Request level transactions are used when the request is not in the scope of a global or local transaction, which implies "autoCommit" is "true". In a request level transaction, your application does not need to explicitly call commit or rollback, rather every command is assumed to be its own transaction that will automatically be committed or rolled back by the server.

The Data Virtualization Server can perform updates through virtual tables. These updates might result in an update against multiple physical systems, even though the application issues the update command against a single virtual table. Often, a user might not know whether the queried tables actually update multiple sources and require a transaction.

For that reason, the Data Virtualization Server allows your application to automatically wrap commands in transactions when necessary. Because this wrapping incurs a performance penalty for your queries, you can choose from a number of available wrapping modes to suit your environment. You need to choose between the highest degree of integrity and performance your application needs. For example, if your data sources are not transaction-compliant, you might turn the transaction wrapping off (completely) to maximize performance.

You can set your transaction wrapping to one of the following modes:

  1. ON: This mode always wraps every command in a transaction without checking whether it is required. This is the safest mode.
  2. OFF: This mode never automatically wraps a command in a transaction or check whether it needs to wrap a command. This mode can be dangerous as it will allow multiple source updates outside of a transaction without an error. This mode has best performance for applications that do not use updates or transactions.
  3. DETECT: This mode assumes that the user does not know to execute multiple source updates in a transaction. The Data Virtualization Server checks every command to see whether it is a multiple source update and wraps it in a transaction. If it is single source then uses the source level command transaction. You can set the transaction mode as a property when you establish the Connection or on a per-query basis using the execution properties. For more information on execution properties, see the section Execution Properties

14.2.1. Multiple Insert Batches

When issuing an INSERT with a query expression (or the deprecated SELECT INTO), multiple insert batches handled by separate source INSERTS may be processed by the Data Virtualization server. Be sure that the sources that you target support XA or that compensating actions are taken in the event of a failure.

14.3. Using Global Transactions

Global or client XA transactions are only applicable to JDBC clients. They all the client to coordinate multiple resources in a single transaction. To take advantage of XA transactions on the client side, use the Data VirtualizationDataSource (or Data Virtualization Embedded with transaction detection enabled).

When an XAConnection is used in the context of a UserTransaction in an application server, such as JBoss, WebSphere, or Weblogic, the resulting connection will already be associated with the current XA transaction. No additional client JDBC code is necessary to interact with the XA transaction.

Usage with UserTransaction

   UserTransaction ut = context.getUserTransaction();
   try {
      ut.begin();
      Datasource oracle = lookup(...)
      Datasource teiid = lookup(...)

      Connection c1 = oracle.getConnection();
      Connection c2 = teiid.getConnection();

      // do something with Oracle connection
      // do something with Data Virtualization connection
      c1.close();
      c2.close();
      ut.commit();
   } catch (Exception ex) {
       ut.rollback();
   }

In the case that you are not running in a JEE container environment and you have your own transaction manger to co-ordinate the XA transactions, code will look some what like below.

Manual Usage of XA transactions

XAConnection xaConn = null;
XAResource xaRes = null;
Connection conn = null;
Statement stmt = null;

try {
  xaConn = <XADataSource instance>.getXAConnection();
  xaRes = xaConn.getXAResource();
  Xid xid = <new Xid instance>;
  conn = xaConn.getConnection();
  stmt = conn.createStatement();

  xaRes.start(xid, XAResource.TMNOFLAGS);
  stmt.executeUpdate("insert into …");
  <other statements on this connection or other resources enlisted in this transaction>
  xaRes.end(xid, XAResource.TMSUCCESS);

  if (xaRes.prepare(xid) == XAResource.XA_OK) {
    xaRes.commit(xid, false);
  }
}
catch (XAException e) {
  xaRes.rollback(xid);
}
finally {
  <clean up>
}

With the use of global transactions multiple Data Virtualization XAConnections may participate in the same transaction. The Data Virtualization JDBC XAResource "isSameRM" method returns "true" only if connections are made to the same server instance in a cluster. If the Data Virtualization connections are to different server instances then transactional behavior may not be the same as if they were to the same cluster member. For example, if the client transaction manager uses the same XID for each connection (which it should not since isSameRM will return false), duplicate XID exceptions may arise from the same physical source accessed through different cluster members. More commonly if the client transaction manager uses a different branch identifier for each connection, issues may arise with sources that lock or isolate changes based upon branch identifiers.

14.4. Restrictions

14.4.1. Application Restrictions

The use of global, local, and request level transactions are all mutually exclusive. Request level transactions only apply when not in a global or local transaction. Any attempt to mix global and local transactions concurrently will result in an exception.

14.4.2. Enterprise Information System (EIS) compatibility

The underlying data source that represents the EIS system and the EIS system itself must support XA transactions if they want to participate in distributed XA transaction through Data Virtualization. If source system does not support the XA, then it can not fully participate in the distributed transaction. However, the source is still eligible to participate in data integration without the XA support.

The participation in the XA transaction is automatically determined based on the source XA capability. It is user’s responsibility to make sure that they configure a XA resource when they require them to participate in distributed transaction.