app servers.
Let us say you have a update method that updates multiple XA resources and one Non-XA resource, I want to commit all or none. I dont
want my Non-XA resource to participate in global transaction, so I will create a method that will do updates to Non-XA resource
and I use the transaction attribute "NotSupported" and I call this method from a method that particpates in transaction. See the
following snippet to understand this.
/* It updates mutliple XA resources and one Non-XA resource. Transaction-attribute can be Requires, Requires-New, Mandatory */
public void boolean update() throws Exception{
boolean commit = true;
try{
commit = updateXA();
if ( false == commit ){
return false;
}
/* It came here means, XA updates are successful */
/* Now update Non-XA resource */
commit = updateNonXA();
}
catch(Exception e){
commit = false;
throw e;
}
finally{
if( !commit ){
/*rollback the entire transaction that rolls back the resources that participated in transaction.
In a way it rolls back XA updates if any
No need to rollback Non-XA updates, if non-xa update went through successfully, we dont come here
If Non-XA update is not done then we dont roll back its changes, we need only XA changes.*/
ctx.rollbackOnly();
}
}
}
/* Do updates to multiple XA resources here
Transaction-attribute must be Mandatory or Requires(we know the caller is running in transaction ;) )*/
public void boolean update() throws Exception{
}
/* Do updates to single Non-XA resources here
Transaction-attribute must be NotSupported, It should ignore the global transaction */
public void boolean update() throws Exception{
}
Another good post from Mike
- POSTED BY: Mike Spille
- POSTED ON: August 20 2003 09:55 EDT
- in response to Timur Evdokimov
XA does generally exact a performance penalty. In non-XA operations, typically there's only one commit that does any signficant amount of work - the RDBMS commit. In XA, you end up with each "Resource Manager" (JMS, RDBMS, etc) commiting, and the Transaction Manager (the app server) also having to keep track of transactions.
In XA mode, the TM and each RM needs to have a transaction log, and typically the following happens:
- App or container asks for commit
- Foreach Resource:
- Call resource prepare - results in "hardening" of data and a disk force
- If all resources voted "yes", TM writes a prepared record to its tran log (also a disk force)
- Foreach Resource:
- Call resource commit - results in a disk force and data is committed
- "soft write" by the TM that the commit is complete (e.g. write w/ no disk force).
If you have two resources, such as your case (JMS and RDBMS), there are five disk forces involved (2 for JMS, 2 for RDBMS, 1 for TM).
The overhead will vary tremendously depending on the environment you're in and the products you're using, but it's often on the order of 50 milliseconds-100 milliseconds on average.
As an earlier thread on TSS indicated, on the JMS side not all JMS providers disk sync by default - they soft write without guaranteeing that data has been written to disk. This may be why you're not seeing as great of a performance hit - check your JMS providers' docs for details on "disk syncing" or "disk forcing" or "synchronized writes". Note also that some JMS providers don't use a transaction log at all, such as JBoss' JMS provider. And some JMS providers get it partially write - for example, one commercial JMS provider only durably records transactions for persistent messages, and (incorrectly) leaves transactions involving non-persistent messages hanging in the breeze.
For providers which have a log but don't disk force, a hard failure of the server (process or machine) can result in lost transactions. For providers which don't have transaction logs at all, the server can't preserve transactions across startup/shutdown of the JMS server at all.
On the TM side, Websphere versions 4.x and 5.x definitely involve a disk force when all resources are prepared. I don't remember what JBoss does.
In XA mode, the TM and each RM needs to have a transaction log, and typically the following happens:
- App or container asks for commit
- Foreach Resource:
- Call resource prepare - results in "hardening" of data and a disk force
- If all resources voted "yes", TM writes a prepared record to its tran log (also a disk force)
- Foreach Resource:
- Call resource commit - results in a disk force and data is committed
- "soft write" by the TM that the commit is complete (e.g. write w/ no disk force).
If you have two resources, such as your case (JMS and RDBMS), there are five disk forces involved (2 for JMS, 2 for RDBMS, 1 for TM).
The overhead will vary tremendously depending on the environment you're in and the products you're using, but it's often on the order of 50 milliseconds-100 milliseconds on average.
As an earlier thread on TSS indicated, on the JMS side not all JMS providers disk sync by default - they soft write without guaranteeing that data has been written to disk. This may be why you're not seeing as great of a performance hit - check your JMS providers' docs for details on "disk syncing" or "disk forcing" or "synchronized writes". Note also that some JMS providers don't use a transaction log at all, such as JBoss' JMS provider. And some JMS providers get it partially write - for example, one commercial JMS provider only durably records transactions for persistent messages, and (incorrectly) leaves transactions involving non-persistent messages hanging in the breeze.
For providers which have a log but don't disk force, a hard failure of the server (process or machine) can result in lost transactions. For providers which don't have transaction logs at all, the server can't preserve transactions across startup/shutdown of the JMS server at all.
On the TM side, Websphere versions 4.x and 5.x definitely involve a disk force when all resources are prepared. I don't remember what JBoss does.
No comments:
Post a Comment