Types of Transactions

Transactions can be either local (also called standard) or global (also called distributed), depending on the resources and the data sources involved. Most enterprise applications use some sort of transactions. J2EE applications and components are designed with transactions in mind. In the following sections, we will cover both types of transaction types with respect to JDBC and JMS applications.

Local Transactions

A local transaction deals with a single resource manager. Each resource manager provides access to a single external resource through a collection of configurations and processes (see Figure 16.1). A resource manager enforces the ACID properties for a specific external resource, such as an RDBMS or a JMS provider. J2EE applications access the resource manager through a resource adapter. For example, a transaction-aware JDBC API is a common resource adapter. A JMS API is another resource adapter that provides access to a messaging system (JMS provider). The JCA (J2EE Connector Architecture) is a common adapter that provides access to legacy systems (ERP or CRM systems) through a JCA adapter.

Figure 16.1. Local transactions.


Transaction demarcation denotes the events—such as the begin, commit, and rollback events—that occur at each transaction boundary. J2EE applications and components provide two methods of transaction demarcation, either programmatically or declaratively. In the programmatic description, the bean's developer explicitly demarcates the transaction boundary in the bean's code. This type of transaction demarcation is called a bean-managed transaction. The declarative approach is when the demarcation is specified in the beanís deployment descriptor. The EJB container will manage all transaction demarcation, and will propagate the transaction context across different beans, and even across EJB containers. This type of transaction demarcation is called a container-managed transaction.

We will cover local transactions with respect to JDBC and JMS. JCA transactions are beyond the scope of this book.

JDBC Local Transactions

As you learned on Day 9, JDBC controls local transactions through the Connection object. Both transaction settings and transaction demarcations are performed on the Connection object. By default, all database operations through the JDBC driver are transactional. To change this behavior, you learned to use setAutoCommit(false) on the Connection object to manage your transactions. You also learned to set other transaction demarcations using the commit() or rollback() method on the Connection object.

Transaction Levels of Isolation

To control concurrency among different transactions in accessing shared data, the DBMS provides the concept of locking. Locking protects data integrity and consistency. On the other hand, it is a costly operation and has a negative impact on overall performance. Transaction levels-of-isolation is the concept by which components can be set to control the multiple interactions with the shared resource. The transaction level of isolation is set by the application server to control the application behavior. The levels of isolation depend on the application, the nature of the data, and the frequency of updates.

Note

Note that in auto-commit mode, in which each Statement is considered a transaction, locks are held for only one Statement. After a lock is set, it will remain until the transaction is committed or rolled back.


Here are some of the issues related to transaction isolation:

  • A dirty read occurs when the first transaction reads uncommitted changes made by the second transaction. If the second transaction is rolled back, the data read by the first transaction becomes invalid because the rollback undoes the changes.

  • A phantom read occurs when new records added to the database are detectable by transactions that started prior to the insert.

  • A repeatable read is when the data read is guaranteed to look the same if read again during the same transaction. This occurs when each transaction is Serializable.

How locks are set is determined by the transaction isolation level, which can range from not supporting transactions at all to supporting transactions that enforce very strict access rules.

Table 16.1 summarizes the transaction isolation levels, from the least restrictive to the most restrictive. It lists also how the transaction isolation level affects system performance.

Table 16.1. Transaction Isolation Levels
Transaction LevelDirty ReadPhantom ReadNonrepeatableRestrictionPerformance
TRANSACTION_NONEN/AN/AN/ALowestFastest
TRANSACTION_UNCOMMITEDYesYesYesLowFaster
TRANSACTION_READ_COMMITEDNoYesYesHighFast
TRANSACTION_REPEATABLE_READNoYesNoHigherMedium
TRANSACTION_SERIALIZABLENoNoNoHighestSlow

From Table 16.1, you can see that as the isolation levels become more restrictive, the performance of the transaction decreases. A TRANSACTION_SERIALIZABLE isolation level, for example, involves more locks in the database; therefore, it has a greater impact on the transaction's performance.

You can control the transaction isolation level using the method setTransactionIsolation() of the Connection object. You also can examine the transaction level for a connection using the getTransactionIsolation() method. Here is an example:

// Begin a new transaction by disable transaction
// auto-mode on the Connection object
conn.setAutoCommit(false);
// Set transaction isolation level on the Connection object
conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
// Create a Statement object using the Connection object
Statement stmt = conn.createStatement();
try {
  stmt.executeUpdate("UPDATE Student set fname='Laura' where id =5");
  conn.commit();
} catch (SQLException ex) {
  conn.rollback();
  stmt.close();
}

Note

Transaction isolation level cannot be set during a transaction.


In EJB, for container-managed transactions, isolation levels are set in the bean's deployment descriptor. However, in a bean-managed transaction, the bean's developer sets the transaction isolation level in the bean's code. These approaches will be covered in next two days (Days 17 and 18).

Caution

Different EJB containers allow different levels of granularity for setting isolation levels; some containers defer this responsibility to the database. In some containers, you might be able to set different isolation levels for different methods, whereas other products might require the same isolation level for all methods in a bean or, possibly, all beans in the container.


Note

If a JDBC Connection participates in a distributed transaction, the JTA transaction manager will ignore both the auto-commit mode and isolation level settings during the distributed transaction. Distributed transactions will be covered in the next section.


JMS Local Transactions

As you learned on Day 13, JMS controls local transaction demarcation through the Session object (QueueSession in PTP mode; TopicSession in Pub/Sub mode). By default, a new session created from its corresponding connection is not transactional. To change this behavior, create a transacted session by setting the transacted parameter to true of the method createQueueSession(true) or createTopicSession(true). A transaction will be committed only when you use the method commit() or rollback() on the session object. In JMS, transactions are chained, which means that a new transaction automatically starts as soon as the current transaction is committed or rolled back.

In JMS, local transactions are handled by a JMS producer or consumer, or, in some cases, a JMS router (a combined producer and consumer). The following is an example of a local transaction used by a JMS's queue sender:

// Create a transacted session for a QueueSender
QueueSession qSession =
    qCon.createQueueSession (true, Session.AUTO_ACKNOWLEDGE);
QueueSender qSender = qSession.createSender (myQueue);
qSender.send(msg);
qSession.commit();

In the preceding example, the message msg will not be delivered until the commit() is completed. Here is another example of a QueueReceiver in a transacted session:

// Create a transacted session for a QueueReceiver
QueueSession qSession =
         qCon.createQueueSession (true, Session.AUTO_ACKNOWLEDGE);
QueueReceiver qReceiver = qSession.createReceiver (myQueue);
TextMessage msg = (TextMessage) qRec.receive();
qSession.commit();

A message router (sometimes called a message broker) is a common application used to deliver messages between multiple producers and multiple consumers. Here is an example of a transacted session in a message-router scenario:

// Create a transacted session for a message router
QueueSession qSession =
          qCon.createQueueSession (true, Session.AUTO_ACKNOWLEDGE);
QueueReceiver qReceiver = qSession.createReceiver (myQueue);
TextMessage msg = (TextMessage) qReceiver.receive();
QueueSender qSender = qSession.createSender(myQueue);
qSender.send(msg);
qSession.commit();

Similarly, a transacted session can be created using a TopicSession in the Pub/Sub model.

Distributed Transactions

A distributed transaction executes operations on different resources to accomplish its workflow requirement. Database and middleware vendors have developed the X/Open Distributed Transaction Protocol (DTP) model to define the rules and guidelines for distributed transactions.

Two-Phase Commit Protocol

To perform a distributed transaction, the transaction manager coordinates the transaction execution across multiple resource managers. Because all participant resource managers are not aware of each other, an algorithm has been established, as a standard protocol, to control the interactions of all participants. The two-phase commit (2PC) protocol enforces the ACID properties and is implemented into two phases:

  • Phase 1: This is the preparation phase. The transaction manager, or coordinator, asks each resource manager to prepare to commit (also called vote to commit). This involves assigning locks to shared resources without actually writing data to permanent storage. Each resource manager replies with its readiness to execute.

  • Phase 2: If all the resource managers reply with successful preparation, the transaction manager requests all to commit their changes; otherwise, it tells them all to roll back and indicates transaction failure to the application. The transaction will succeed if and only if all resource managers commit successfully.

Some variants of the 2PC implementation allow for full transaction success, even if one resource manager fails. The transaction manager saves the failed part to be recovered later.

Note

If there is only one participant in the transaction, the transaction manager avoids the 2PC, and uses the local transaction's single-phase commit protocol.


Distributed Transaction Model

A distributed transaction often spans multiple resource managers. Each resource manager may be hosted on a heterogeneous processing node, manages its own threads of control, and has a different resource adapter. According to DTP, a distributed transaction model is more complex than a local one; more participants are involved in a distributed transaction model. The following list describes the participants in a distributed transaction:

  • Transaction Originator: The client initiates the transaction. It can be a Java application in the client tier, a servlet in the Web tier, or a session bean in the EJB tier. It also can be a JMS producer/consumer in the Web tier or the EJB tier.

  • Transaction Manager: Manages transactions on behalf of the originator. It enforces the transaction ACID properties by coordinating access across all participating resource managers. When resource managers fail during transactions, transaction managers help resource managers decide whether to commit or roll back pending transactions. JTA implements the transaction manager in J2EE architecture.

  • Recoverable Resource: Provides persistent storage for transaction data to ensure durability of the transaction. In most cases, this is often a database or a flat file resource.

  • Resource Manager: One of the aforementioned transaction-aware types. This can manage a DBMS, a JMS provider, or a JCA resource.

Figure 16.2 summarizes the protocols and interactions among all participants of a distributed transaction.

Figure 16.2. Distributed transaction model.


The transaction manager interacts with all participant resource managers through the XA protocol (defined by X/Open to implement the 2PC algorithm). Each of the resource adapters complies with the XA protocol by providing XA-compliant interfaces. Both JDBC API and JMS API provide XA-compliant interfaces that are designed to be used by the container vendor and not by the application developer. Application clients interface with the transaction manager through the TX protocol (which includes all the transaction demarcation events).

In the case of local transactions, applications interact directly with the resource manager. But in distributed transactions, applications are required to interface with the transaction manager, which coordinates all transaction demarcations among multiple resource managers. This decoupling of transaction management simplifies the task of writing complex enterprise applications.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.146.35.72