Chapter 32. Set Up Transactions

32.1. About Transactions

32.1.1. About Transactions

A transaction consists of a collection of interdependent or related operations or tasks. All operations within a single transaction must succeed for the overall success of the transaction. If any operations within a transaction fail, the transaction as a whole fails and rolls back any changes. Transactions are particularly useful when dealing with a series of changes as part of a larger operation.

In Red Hat JBoss Data Grid, transactions are only available in Library mode.

32.1.2. About the Transaction Manager

In Red Hat JBoss Data Grid, the Transaction Manager coordinates transactions across a single or multiple resources. The responsibilities of a Transaction Manager include:

  • initiating and concluding transactions
  • managing information about each transaction
  • coordinating transactions as they operate over multiple resources
  • recovering from a failed transaction by rolling back changes

32.1.3. XA Resources and Synchronizations

XA Resources are fully fledged transaction participants. In the prepare phase (see About Two Phase Commit (2PC) for details), the XA Resource returns a vote with either the value OK or ABORT. If the Transaction Manager receives OK votes from all XA Resources, the transaction is committed, otherwise it is rolled back.

Synchronizations are a type of listener that receive notifications about events leading to the transaction life cycle. Synchronizations receive an event before and after the operation completes.

Unless recovery is required, it is not necessary to register as a full XA resource. An advantage of synchronizations is that they allow the Transaction Manager to optimize 2PC (Two Phase Commit) with a 1PC (One Phase Commit) where only one other resource is enlisted with that transaction (last resource commit optimization). This makes registering a synchronization more efficient.

However, if the operation fails in the prepare phase within Red Hat JBoss Data Grid, the transaction is not rolled back and if there are more participants in the transaction, they can ignore this failure and commit. Additionally, errors encountered in the commit phase are not propagated to the application code that commits the transaction.

By default JBoss Data Grid registers to the transaction as a synchronization.

32.1.4. Optimistic and Pessimistic Transactions

Pessimistic transactions acquire the locks when the first write operation on the key executes. After the key is locked, no other transaction can modify the key until this transaction is committed or rolled back. It is up to the application code to acquire the locks in correct order to prevent deadlocks.

With optimistic transactions locks are acquired at transaction prepare time and are held until the transaction commits (or rolls back). Also, Red Hat JBoss Data Grid sorts keys for all entries modified within a transaction automatically, preventing any deadlocks occurring due to the incorrect order of keys being locked. This results in:

  • less messages being sent during the transaction execution
  • locks held for shorter periods
  • improved throughput
Note

Read operations never acquire any locks. Acquiring the lock for a read operation on demand is possible only with pessimistic transactions, using the FORCE_WRITE_LOCK flag with the operation.

32.1.5. Write Skew Checks

A common use case for entries is that they are read and subsequently written in a transaction. However, a third transaction can modify the entry between these two operations. In order to detect such a situation and roll back a transaction Red Hat JBoss Data Grid offers entry versioning and write skew checks. If the modified version is not the same as when it was last read during the transaction, the write skew checks throws an exception and the transaction is rolled back.

Enabling write skew check requires the REPEATABLE_READ isolation level. Also, in clustered mode (distributed or replicated modes), set up entry versioning. For local mode, entry versioning is not required.

Important

With optimistic transactions, write skew checks are required for (atomic) conditional operations.

32.1.6. Transactions Spanning Multiple Cache Instances

Each cache operates as a separate, standalone Java Transaction API (JTA) resource. However, components can be internally shared by Red Hat JBoss Data Grid for optimization, but this sharing does not affect how caches interact with a Java Transaction API (JTA) Manager.

32.2. Configure Transactions

32.2.1. Configure Transactions (Library Mode)

In Red Hat JBoss Data Grid, transactions in Library mode can be configured with synchronization and transaction recovery. Transactions in their entirety (which includes synchronization and transaction recovery) are not available in Remote Client-Server mode.

In order to execute a cache operation, the cache requires a reference to the environment’s Transaction Manager. Configure the cache with the class name that belongs to an implementation of the TransactionManagerLookup interface. When initialized, the cache creates an instance of the specified class and invokes its getTransactionManager() method to locate and return a reference to the Transaction Manager.

In Library mode, transactions are configured as follows:

Configure Transactions in Library Mode (XML Configuration)

<local-cache name="default" <!-- Additional configuration information here -->>
	<transaction mode="BATCH"
	    stop-timeout="60000"
	    auto-commit="true"
	    protocol="DEFAULT"
	    recovery-cache="recoveryCache">
	<locking <!-- Additional configuration information here --> >
	<versioning scheme="SIMPLE"/>
  <!-- Additional configuration information here -->
</local-cache>

  1. Enable transactions by defining a mode. By default the mode is NONE, therefore disabling transactions. Valid transaction modes are BATCH, NON_XA, NON_DURABLE_XA, FULL_XA.
  2. Define a stop-timeout, so that if there are any ongoing transactions when a cache is stopped the instance will wait for ongoing transactions to finish. Defaults to 30000 milliseconds.
  3. Enable auto-commit, so that single operation transactions do not need to be manually initiated. Defaults to true.
  4. Define the commit protocol in use. Valid commit protocols are DEFAULT and TOTAL_ORDER.
  5. Define the name of the recovery-cache, where recovery related information is kept. Defaults to _recoveryInfoCacheName_.
  6. Enable versioning of entries by defining the scheme attribute as SIMPLE. Defaults to NONE, indicating that versioning is disabled.

32.2.2. Configure Transactions (Remote Client-Server Mode)

Red Hat JBoss Data Grid does not offer transactions in Remote Client-Server mode. The default configuration is non-transactional, which is set as follows:

Default Transaction Configuration in Remote Client-Server Mode

<cache>
	<!-- Additional configuration elements here -->
 	<transaction mode="NONE" />
	<!-- Additional configuration elements here -->
</cache>

Important

JBoss Data Grid in Remote Client-Server mode does not support transactions directly. However, if you use conditional operators such as replaceWithVersion, putIfAbsent, or removeWithVersion you should enable transactions.

To enable transactions for the use of conditional operators use the following configuration:

Transaction Configuration for Conditional Operators in Remote Client-Server Mode

<cache>
        <!-- Additional configuration elements here -->
        <transaction mode="NON_XA" />
        <!-- Additional configuration elements here -->
</cache>

32.3. Transaction Recovery

32.3.1. Transaction Recovery

The Transaction Manager coordinates the recovery process and works with Red Hat JBoss Data Grid to determine which transactions require manual intervention to complete operations. This process is known as transaction recovery.

JBoss Data Grid uses JMX for operations that explicitly force transactions to commit or roll back. These methods receive byte arrays that describe the XID instead of the number associated with the relevant transactions.

The System Administrator can use such JMX operations to facilitate automatic job completion for transactions that require manual intervention. This process uses the Transaction Manager’s transaction recovery process and has access to the Transaction Manager’s XID objects.

32.3.2. Transaction Recovery Process

The following process outlines the transaction recovery process in Red Hat JBoss Data Grid.

The Transaction Recovery Process

  1. The Transaction Manager creates a list of transactions that require intervention.
  2. The system administrator, connected to JBoss Data Grid using JMX, is presented with the list of transactions (including transaction IDs) using email or logs. The status of each transaction is either COMMITTED or PREPARED. If some transactions are in both COMMITTED and PREPARED states, it indicates that the transaction was committed on some nodes while in the preparation state on others.
  3. The System Administrator visually maps the XID received from the Transaction Manager to a JBoss Data Grid internal ID. This step is necessary because the XID (a byte array) cannot be conveniently passed to the JMX tool and then reassembled by JBoss Data Grid without this mapping.
  4. The system administrator forces the commit or rollback process for a transaction based on the mapped internal ID.

32.3.3. Transaction Recovery Example

The following example describes how transactions are used in a situation where money is transferred from an account stored in a database to an account stored in Red Hat JBoss Data Grid.

Money Transfer from an Account Stored in a Database to an Account in JBoss Data Grid

  1. The TransactionManager.commit() method is invoked to run the two phase commit protocol between the source (the database) and the destination (JBoss Data Grid) resources.
  2. The TransactionManager tells the database and JBoss Data Grid to initiate the prepare phase (the first phase of a Two Phase Commit).

During the commit phase, the database applies the changes but JBoss Data Grid fails before receiving the Transaction Manager’s commit request. As a result, the system is in an inconsistent state due to an incomplete transaction. Specifically, the amount to be transferred has been subtracted from the database but is not yet visible in JBoss Data Grid because the prepared changes could not be applied.

Transaction recovery is used here to reconcile the inconsistency between the database and JBoss Data Grid entries.

Note

To use JMX to manage transaction recoveries, JMX support must be explicitly enabled.

32.4. Deadlock Detection

32.4.1. Deadlock Detection

A deadlock occurs when multiple processes or tasks wait for the other to release a mutually required resource. Deadlocks can significantly reduce the throughput of a system, particularly when multiple transactions operate against one key set.

Red Hat JBoss Data Grid provides deadlock detection to identify such deadlocks. Deadlock detection is enabled by default.

32.4.2. Enable Deadlock Detection

Deadlock detection in Red Hat JBoss Data Grid is enabled by default, and may be configured by adjusting the deadlock-detection-spin attribute of the cache configuration element, as seen below:

<local-cache [...] deadlock-detection-spin="1000"/>

The deadlock-detection-spin attribute defines how often lock acquisition is attempted within the maximum time allowed to acquire a particular lock (in milliseconds). This value defaults to 100 milliseconds, and negative values disable deadlock detection.

Deadlock detection can only be applied to individual caches. Deadlocks that are applied on more than one cache cannot be detected by JBoss Data Grid.