|
YOUR FEEDBACK
Did you read today's front page stories & breaking news?
SYS-CON.TV |
TOP THREE LINKS YOU MUST CLICK ON Architecture Transactions - When They're Hot and When They're Not
Transactions - When They're Hot and When They're Not
By: Peter Holditch
Feb. 6, 2002 12:00 AM
Sad, I mused - you don't often see that any more. My mind then wandered to hoping that, as technologists, we aren't somehow tacitly colluding in the erosion of the fabric that holds society together. Hmm, I seem to have come over all melancholy. Excuse me whilst I visit The Hunger Site...
Understanding JTA
At a high level, all J2EE specifications fall into two broad categories: those providing a point technology and those providing a layer that binds a discrete set of specifications into the unified platform that J2EE defines. By way of illustration, messaging between message producers and consumers is a point problem addressed by the JMS specification. Likewise, how to manage server-side business logic accessed from a relatively large and potentially diverse client population is a point problem dealt with by EJB. In the other camp, providing a general purpose naming system for advertising and looking up "stuff" is the job of JNDI, and demarcating logical groups of data updates done using various "point solution" specifications is the job of JTA. To cement these two classes of specifications together into a unified platform, it's important to understand how they relate to one another. In the case of JTA, transactions are typically propagated through the XAResource extension to various interfaces. They're propagated to databases through the JDBC interface, and into messaging systems through the JMS interface; the J2EE Connector architecture provides for them to be propagated to external applications and - in the specific case of WebLogic Server - into Tuxedo applications and potentially from there to mainframe systems via the WebLogic Tuxedo Connector. Finally, with the session synchronization interface, any business logic you dream up can be informed before and after a transaction goes through the commit phase. On the face of it, anything likely to affect the durable state of an application, can be involved in a JTA transaction. This gives application architects the possibility of dividing the work of their application into however many atomic lumps of functionality they desire, at whatever level of granularity they see. Of course, J2EE is merely a toolkit; just because you can do something with it, doesn't mean it's a good idea. I always get enraged when I hear things like "Don't use Entity Beans, they don't work," since that seems to me to be akin to saying "Don't use boxing gloves, they don't work." While this might be seen as words of wisdom to someone starting guitar lessons, it comes across as somewhat less perceptive if said to someone on their way to a boxing ring. Enough hyperbole. The rest of this month's column will explore how transactions might be used to best effect in an application.
Transactions and JDBC Databases
The next thought, after transaction and database, is often "performance hit" and people immediately run screaming back to database local transactions. In reality, the perceived "hit" is not big. WebLogic Server optimizes commit processing to a single commit-only phase if a given transaction turns out to only be addressing a single RM instance. This means any overhead caused by a JTA transaction is largely confined to the mapping between the WebLogic Server transaction ID and the database's own notion of a transaction, which should be a fast lookup inside the database. The benefit of using JTA transactions from the start is that, as you come to reuse your components in the future, they'll be able to participate in transactions with larger scope without requiring code changes. This is a big win in terms of maintenance cost and increased ROI through component re-use. Whilst talking about single or multiple database instances, it's also worth considering the impact of JDBC connection pools. The transaction manager will start a new transaction branch for every connection pool it touches. This means that even if you're only accessing one physical database instance, you'll get a two-phase commit if you do so through two different connection pools. Not only dioes this defeat the one-phase commit optimization just mentioned, but typically data locked by one transaction branch isn't visible in another. This means you can access the same data twice, in the context of the transaction, and get a deadlock situation between branches of the transaction. On the plus side, however, the two branches can't cause one another unforeseen side effects by manipulating data both rely on in unexpected ways. These issues must be considered when deploying when you decide which components should be accessing which TxDataSources. On locking, there's another thing: any data you modify as part of a transaction will be locked by the database (subject to the JDBC transaction isolation level you set) until the transaction completes. In this context, "completes" means when the second phase of the commit happens, not when your logic finishes executing. Clearly, if your customer database gets locked in one gigantic transaction, your system will come to a standstill until the transaction completes.
Non-JDBC transactions
Remember, now, the youth helping the old lady across the road. This situation is equivalent to doing a two-phase commit between an old lady and a youth, the goal of which is to get old ladies safty across the road. While that's a laudable objective, it's not ideal if you want to get a large number of youths across the street. In this case, you'll let the youths dodge traffic as nimbly as they can and leave the old ladies to effect their traversals as traffic permits. Even having off-loaded the old ladies, the throughput of road-crossing youths will be greatest if you don't force them to cross as a group. This is analogous to lots of small transactions, as opposed to one large one. We're now moving into the realm of JMS and transactions.
Introduce Some Asynchronicity
Another reason to use JMS and transactions combined is to protect applications from resources that don't support transactions, such as the J2EE CA cases discussed earlier. If you front-end a transaction-unaware application with a JMS queue, then you are guaranteed that it will update at least once at some future point, if and only if the update transaction commits. This avoids the potentially far-from-trivial task of backing out changes made to application state through "compensating transaction" logic if a transaction rolls back unexpectedly after a real-time update to the non-transactional system. Of course, the downside is that the transaction-unaware application must be capable of detecting multiple repeat updates, since updates could be resubmitted to it if it fails while consuming messages. This is easy if the application's behavior is idempotent (that is, calling it twice with the same input data will leave it in the same state as only calling it once) but harder in other cases. For example, a SetCustomerAddress method can be called repeatedly with the same data to no ill effect, whereas an IncreaseAccountBalance method, if called twice, will try and create money from nowhere. While this would be a pleasant surprise if the account in question is your own, it probably isn't allowed in the business domain.
Summary
That concludes this month's column. Next month, Transactions: the Saga Continues, on business transactions, two-phase commit, and other stories. BEA WEBLOGIC LATEST STORIES
SUBSCRIBE TO THE WORLD'S MOST POWERFUL NEWSLETTERS SUBSCRIBE TO OUR RSS FEEDS & GET YOUR SYS-CON NEWS LIVE!
|
SYS-CON FEATURED WHITEPAPERS BREAKING NEWS FROM THE WIRES
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||