Principles and applications of Java distributed Transactions (RPM)

Source: Internet
Author: User
Tags connection pooling naming convention

JTA (Java Transaction API) allows applications to perform distributed transactions-access and update data on two or more network computer resources. The JTA support of the JDBC driver greatly enhances the data access capability.

The purpose of this article is to provide a high-level overview of the Java Transaction API (JTA), as well as content related to distributed transactions. A transaction defines a unit of work logic that is either completely successful or produces no results. A distributed transaction is simply a transaction that accesses and updates data on two or more network resources, so it must be equivalent between those resources. In this article, our main concern is how to deal with relational database systems.

The components we want to discuss in the Distributed transaction Processing (DTP) model are:

Application

Application Server

Transaction management procedures

Resource Adapter

Resource Management Program

In future content, we will describe these components and their relationship to JTA and database access.

Accessing the database

It is better to think of the components contained in distributed transactions as separate processes rather than their location on a particular computer. Some of these components can be stored in a single machine, or can be distributed among several machines. The graphs in the following example can be displayed on a specific computer, but the relationship between these operations must be considered first and foremost.

The simplest example: an application for local database transaction processing

The simplest form of relational database access consists only of applications, resource management programs, and resource adapters. An application is simply an end-user access point that sends requests to the database and gets data from the database

The resource management program we are discussing is a relational database management system (RDBMS), such as Oracle or SQL Server. All of the actual database management is handled by this component.

A resource adapter is a communication pipeline component between external spaces, or a request translator, which in this case is an application and a resource management program. In our discussion, this is a JDBC driver.

The following description is a description of the Resource Manager local transaction processing, which means that a transaction is limited to a specific enterprise database.

The application sends a request for the JDBC driver data and then translates the request and sends it over the network to the database. The database sends the data back to the driver, and then sends the translated results back to the application, as shown in:


This example illustrates the basic flow of information in a simplified system; However, today's enterprise uses an application server that adds additional components to the process.

Application Server

An application server is another component of a transaction processing operation. The application server handles most of the application operations and obtains some load from the end-user application. Based on the previous example, we can see that the application server has added another operational layer to the transaction:


  

So far, our example illustrates a single local transaction and describes four of the five components of a distributed transaction processing model. The fifth component, the transaction manager, will only begin to be considered when the transaction is about to be allocated.

Distributed transaction processing and transaction management program

As we mentioned earlier, a distributed transaction processing is a transaction that accesses and updates data on two or more network resources.

These resources can consist of several different relational database management systems located on a separate server, such as Oracle, SQL Server, and Sybase; they can also contain several instances of the same database that exist on several different servers. In any case, a distributed transaction process involves the synergy between various resource management programs. This synergy is a transaction management function.

The transaction management program is responsible for making decisions that either commit (commit) or return (rollback) any distributed transaction processing. A commit decision should result in a successful transaction, while the rollback operation keeps the data in the database intact. JTA Specifies a standard Java interface between the transaction manager and another component in a distributed transaction: applications, application servers, and resource management programs. This relationship is shown in the following diagram:



The number box around the transaction manager corresponds to the three interface sections of JTA:

The 1-usertransaction-javax.transaction.usertransaction interface provides applications that can programmatically control the scope of transaction processing. The Javax.transaction.UserTransaction method opens a global transaction and uses the calling thread to associate with the transaction.

The 2-transaction Manager-javax.transaction.transactionmanager interface allows the application server to control the scope of transactions that represent the application being administered.

The 3-xaresource-javax.transaction.xa.xaresource interface is a Java mapping of an industry-standard XA interface based on the X/open CAE specification.

Note that a restrictive link is supported by the Xaresource interface of the JDBC driver. The JDBC driver must support two normal JDBC interactions: the application and/or application server, and the xaresource portion of the JTA.

Developers writing application-level code do not care about the details of distributed transaction management. This is the work of the Distributed transaction processing infrastructure-Application server, transaction manager, and JDBC driver. The only thing to note in the application code is that when the connection is within a distributed transaction scope, a method that affects the transaction boundary should not be called. In particular, an application should not call the connection method commit, Rollback, and Setautocommit (true), as they will disrupt the basic structure management of distributed transactions.

Distributed transaction Processing

The transaction manager is the basic component of the basic structure of the distributed transaction; however, the JDBC driver and application server components should have the following characteristics:

The driver should implement the JDBC 2.0 application interface, including the optional package interface Xadatasource and Xaconnection, as well as the JTA interface Xaresource.

The application server should provide a DataSource class for interacting with the basic nodes of the distributed transaction and a connection pooling module (for performance improvement).

The first step in Distributed transaction processing is for the application to send a transaction request to the transaction manager. Although the final commit/rollback decided to treat the transaction as a simple logical unit, it might still include many transactional branches. A transactional branch is associated with a single resource manager that is contained in a distributed transaction. Therefore, requests that are managed by three different relational databases require three transaction branches. Each transaction branch must be committed or returned by the local resource manager. The transaction manager controls the boundaries of the transaction and is responsible for finalizing all the transactions that should be committed or returned. This decision consists of two steps, called two-phase Commit Protocol.

In the first step, the transaction manager polls all the resource managers included in the distributed transaction (relational database management) to see which one is ready to commit. If a resource manager cannot commit, it will not respond and return a specific part of the transaction so that the data is not modified.

In the second step, the transaction manager determines whether the hypervisor in the negative response has the ability to return the entire transaction. If there is no negative response, the translation manager submits the entire transaction and returns the result to the application.

Developers of the Development Event management program code must be related to all three JTA interfaces: UserTransaction, TransactionManager, and Xaresource, all of which are described in the three interface

Sun JTA in specification. The JDBC driver developer only needs to care about the Xaresource interface. This interface is a Java mapping of the industry standard X/open XA protocol that allows a resource manager to participate in transactions. The driver component that connects the Xaresource interface is responsible for the task of "translating" between the transaction manager and the resource management program. The following sections provide examples of Xaresource calls.

JDBC Drivers and Xaresource

To simplify the description of Xaresource, these examples illustrate how an application should use JTA without the application server and event management programs. Basically, the applications in these examples also serve as tasks for application servers and event management programs. Most enterprises use transaction management programs and application servers because they are able to manage distributed transactions more efficiently than one application. However, following these examples, an application developer can test the robustness of JTA support in the JDBC driver. And there are some examples that might not work on a particular database, because there are some intrinsic problems associated with the database.

Before using JTA, you must first implement a XID class to identify the transaction (which will normally be handled by the transaction management program). XID contains three elements: FormatID, Gtrid (global transaction Identifier), and bqual (branch modifier identifier).

FormatID is usually zero, which means that you will use OSI CCR (Open Systems interconnection commitment, concurrency, and recovery standards) to name it. If you use a different format, then the FormatID should be greater than 0. A value of -1 means that the XID is invalid.

Gtrid and bqual can contain 64-byte binaries to identify global transactions and branch transactions, respectively. The only requirement is that Gtrid and bqual must be globally unique. In addition, this can be done by using the naming convention specification specified in the OSI CCR.

The following example illustrates the implementation of XID:

Import javax.transaction.xa.*;
public class Myxid implements Xid
{
protected int FormatID;
protected byte gtrid[];
protected byte bqual[];
Public Myxid ()
{
}
Public Myxid (int formatid, byte gtrid[], byte bqual[])
{
This.formatid = FormatID;
This.gtrid = Gtrid;
This.bqual = bqual;
}

public int Getformatid ()
{
return FormatID;
}

Public byte[] Getbranchqualifier ()
{
return bqual;
}

Public byte[] Getglobaltransactionid ()
{
return Gtrid;
}

}



Second, you need to create a data source for the database you want to use:

Public DataSource Getdatasource ()
Throws SQLException
{
SQLServerDataSource xads = new
Com.merant.datadirect.jdbcx.sqlserver.SQLServerDataSource ();
Xads.setdatasourcename ("SQL Server");
Xads.setservername ("server");
Xads.setportnumber (1433);
Xads.setselectmethod ("cursor");
return xads;
}


Example 1-This example uses a "two-step commit protocol" to commit a branch of a transaction:

Xadatasource xads;
Xaconnection Xacon;
XAResource Xares;
Xid Xid;
Connection con;
Statement stmt;
int ret;
Xads = Getdatasource ();
Xacon = Xads.getxaconnection ("Jdbc_user", "Jdbc_password");
Xares = Xacon.getxaresource ();
con = xacon.getconnection ();
stmt = Con.createstatement ();
XID = new Myxid (New byte[]{0x01}, New byte[]{0x02});
try {
Xares.start (XID, xaresource.tmnoflags);
Stmt.executeupdate ("INSERT into test_table values (100)");
Xares.end (XID, xaresource.tmsuccess);
ret = Xares.prepare (XID);
if (ret = = XARESOURCE.XA_OK) {
Xares.commit (XID, false);
}
}
catch (Xaexception e) {
E.printstacktrace ();
}
finally {
Stmt.close ();
Con.close ();
Xacon.close ();
}


Because the initialization code in all of these examples is the same or very similar, it's just that the code in some important places is different.

Example 2-this example, similar to Example 1, illustrates a return process:

Xares.start (XID, xaresource.tmnoflags);
Stmt.executeupdate ("INSERT into test_table values (100)");
Xares.end (XID, xaresource.tmsuccess);
ret = Xares.prepare (XID);
if (ret = = XARESOURCE.XA_OK) {
Xares.rollback (XID);
}


Example 3-This example shows how a distributed transaction branch aborts, letting the same connections do local transactions, and how they can continue this branch later. The two-step commit of a distributed transaction does not affect local transactions.

XID = new Myxid (New byte[]{0x01}, New byte[]{0x02});
Xares.start (XID, xaresource.tmnoflags);
Stmt.executeupdate ("INSERT into test_table values (100)");
Xares.end (XID, xaresource.tmsuspend);
∥ This update is done outside the scope of the transaction, so it is not affected by the XA return.

Stmt.executeupdate ("INSERT into test_table2 values (111)");
Xares.start (XID, Xaresource.tmresume);
Stmt.executeupdate ("INSERT into test_table values (200)");
Xares.end (XID, xaresource.tmsuccess);
ret = Xares.prepare (XID);

if (ret = = XARESOURCE.XA_OK) {

Xares.rollback (XID);

}

Example 4-This example shows how an XA resource can share different transactions.   created two transaction branches, but they are not part of the same distributed transaction.  JTA allows an XA resource to make a two-step commit on the first branch, although the resource is still associated with the second branch.

xid1 = new myxid (100, new& NBSP;BYTE[]{0X01}, NEW BYTE[]{0X02});
Xid2 = new myxid (100, new byte[]{0x11}, new byte[]{0x22});
Xares.start (xid1, xaresource.tmnoflags);
Stmt.executeupdate ("insert into test_table1 values  (100)");
Xares.end (xid1, xaresource.tmsuccess);
Xares.start (xid2, xaresource.tmnoflags);
Ret = xares.prepare (XID1);
if  (RET == XARESOURCE.XA_OK)  {
Xares.commit (xid2, false);
}
Stmt.executeupdate ("insert into test_table2 values  (200)");
Xares.end (xid2, xaresource.tmsuccess);
Ret = xares.prepare (XID2);
if  (RET == XARESOURCE.XA_OK)  {
Xares.rollback (XID2);
}


Example 5-This example shows how the transaction branches on different connections connect to each other as a separate branch if they are connected to the same resource manager. This feature improves the efficiency of distributed transactions because it reduces the number of two-step commit processing. Two XA connected to the database server will be created. Each connection creates its own XA resource, a regular JDBC connection and a statement. Before the second XA resource starts a transactional branch, it will see whether the same resource manager is used with the first XA resource. If this is an instance, it will join the first branch created on the first XA connection, instead of creating a new branch. Later, this transactional branch uses XA resources to prepare and commit.

Xads = Getdatasource ();
XaCon1 = Xads.getxaconnection ("Jdbc_user", "Jdbc_password");
XaRes1 = Xacon1.getxaresource ();
Con1 = Xacon1.getconnection ();
STMT1 = Con1.createstatement ();

XID1 = new Myxid (New byte[]{0x01}, New byte[]{0x02});
Xares1.start (XID1, xaresource.tmnoflags);
Stmt1.executeupdate ("INSERT into test_table1 values (100)");
Xares1.end (XID, xaresource.tmsuccess);
XaCon2 = Xads.getxaconnection ("Jdbc_user", "Jdbc_password");
XaRes2 = Xacon1.getxaresource ();
Con2 = Xacon1.getconnection ();
STMT2 = Con1.createstatement ();

if (Xares2.issamerm (xaRes1)) {
Xares2.start (XID1, Xaresource.tmjoin);
Stmt2.executeupdate ("INSERT into test_table2 values (100)");
Xares2.end (XID1, xaresource.tmsuccess);
}
else {
Xid2 = new Myxid (New byte[]{0x01}, New byte[]{0x03});
Xares2.start (Xid2, xaresource.tmnoflags);
Stmt2.executeupdate ("INSERT into test_table2 values (100)");
Xares2.end (Xid2, xaresource.tmsuccess);
ret = Xares2.prepare (XID2);
if (ret = = XARESOURCE.XA_OK) {
Xares2.commit (Xid2, false);
}
}
ret = Xares1.prepare (XID1);
if (ret = = XARESOURCE.XA_OK) {
Xares1.commit (Xid1, false);
}


Example 6-This example shows how to recover a prepared or nearly completed branch of a transaction in the error recovery phase. It first tries to return each branch, and if it fails, it tries to get the resource manager to discard the message about the transaction.

Myxid[] XIDs;
XIDs = Xares.recover (Xaresource.tmstartrscan | Xaresource.tmendrscan);
for (int i=0; Xids!=null && I
try {
Xares.rollback (Xids[i]);
}
catch (Xaexception ex) {
try {
Xares.forget (Xids[i]);
}
catch (Xaexception Ex1) {
System.out.println ("Rollback/forget failed:" + ex1.errorcode);
}
}

}

Principles and applications of Java distributed Transactions (RPM)

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.