JBoss Community

Compensating Transactions: When ACID is too much

modified by Paul Robinson in JBoss Transactions Development - View the full document

I'm using this article as a place for people to review a blog post I'm preparing.


The plan is to base my JUDCon:Boston talk roughly on this blog post. In addition to this theory, my presentation will include plenty of code examples for each of the scenarios. These code examples will demonstrate the current design of the compensations API. I'll also be adding sections at the end to explain what we have implemented so far and our future roadmap.


Compensating Transactions: When ACID is too much.

Part 1: Introduction


ACID transactions are a useful tool for application developers and can provide very strong guarantees, even in the presence of failures. However, ACID transactions are not always appropriate for every situation.



ACID transactions are achieved by holding locks on resources and require the ability to rollback changes. In some situations, the blocking nature of the protocol can be too limiting to performance, especially if the transaction is distributed. Also, some actions can’t simply be rolled back; for example, sending an email.



A common strategy for applications that can’t use ACID, is to throw out transactions altogether. However, with this approach you are missing out on many of the benefits that transactions can provide. There are alternative transaction models that relax some of the ACID properties, while still retaining many of the strong guarantees essential for building robust enterprise applications. These should be considered before deciding not to use transactions at all.



In a recent post I talked about the work we are doing, in the Narayana project, to improve support for compensation-based transactions. In this post I’ll show the recent improvements we've made and how this technology can be applied to scenarios in which ACID transactions are frequently seen as inappropriate.



What is a ‘Compensation-based transaction’?

In an ACID transaction, changes are not visible outside of the transaction until it completes. An atomic outcome is guaranteed using a two-phase protocol in which locks are obtained prior to the first phase and released in the second phase. The transaction manager guarantees an atomic outcome, even in the presence of failures.


[TODO: show sequence diagram with locks]


In a compensation-based transaction, changes are visible outside of the transaction as soon as they are made. If any of the participants are unsuccessful, the transaction compensates those participants that have already completed their work. This compensation action is application specific and is required to ‘undo’ the changes made by the transaction. Similarly to the ACID transaction, the transaction manager guarantees an atomic outcome, even in the presence of failures.


[TODO: show sequence diagram with locks]



Compensating Transactions: When ACID is too much.

Part 2: Non-Transactional Work



Non-transactional work

ACID transactions rely on the work supporting rollback. This is fine for work that interacts with transactional resources, such as databases or message queues. However actions like sending an email cannot be rolled back. Here a compensation-based transaction can be used as an alternative. In this case the compensation action is to send another email notifying the recipient of the final outcome.

Alternatively, you may have multiple XA (two-phase) aware resources, but due to performance reasons you need to run them in one-phase mode.



Maybe you have a combination of transactional and non-transactional work. In this case the transactional work can be rolled back, if required, whilst the non-transactional resources are compensated.



Also, you may have transactional resources or services, but, for whatever reason, they will not participate in an existing transaction. This can occur when you try to compose multiple services outside of your control. For example, a travel agent application may compose a transaction of calls to third party services. Providing these services offer an interface for cancelling (compensating) a booking, you should be able to use a compensation-based transaction to coordinate them.



If you find yourself needing to coordinate multiple non-transactional tasks, you should consider using compensations.




Compensating Transactions: When ACID is too much

Part 3: Cross-Domain Distributed Transactions





When your application becomes distributed, you greatly increase the chances of failure. Many of these failures can be tolerated by using a distributed ACID transaction. However, this approach is often dismissed as impractical for a number of reasons.


The first is that distributed transactions tend to take longer to run, due to the increased communication latency. This can cause big problems for your throughput as the duration of held locks greatly increases.


The second issue is that all the servers in the distributed transaction become tightly-coupled. Furthermore, the server that begun the transaction has full control over when the transaction should complete (ignoring the option of making a heuristic decision, which is really bad!). This may be acceptable if all the servers reside in the same business domain, but it’s rarely acceptable for cross-business domain applications.


Compensation-based transactions can be used to solve both of these problems. The latency imposed by the distributed transaction does not result in holding of locks for extended periods as the work is completed immediately, rather than waiting until the end of the transaction. If this work was a database update, it would be committed immediately. A second database update would be made to undo the change, should compensation be required.


Compensation-based transactions also encourage a loosely-coupled architecture as each participant offers a more natural interface to the coordinator. For example, in a flight booking example, the service interface would consist of ‘bookFlight’ and ‘cancelFlight’ operations (‘cancel’ being the compensating action).



Compensating Transactions: When ACID is too much

Part 4: Long Lived Transactions (LLT)




ACID transactions are not particularly well suited for transactions that take a long time to run. This is because they acquire locks on resources as they progress and don’t release them until the transaction completes. In the meantime, other transactions, requiring that data, are blocked. Furthermore, a failure of a long running transaction results in the loss of all work completed so far.



A compensation-based transaction can be composed of multiple short-lived ACID transactions. When each transaction completes, it releases the locks on the data it held, allowing other transactions, requiring that data, to proceed. A compensation action is registered for each ACID transaction. These actions are invoked, in reverse order, for all completed transactions, should the LLT need to be aborted.



Furthermore, should one of these short-lived transactions fail, it could be possible to find an alternative, preventing the entire transaction from failing, and allowing forward progress to be achieved. Also, in some situations, as the transaction progresses, you may decide to abort just part of the transaction.



For example, take a travel booking example. We begin by booking a flight. We then try to book a taxi, but that fails. At this point we don’t want to compensate the flight as it may be fully-booked next time we try. Therefore we try to find an alternative Taxi, which in this example succeeds. Later, in the LLT, we may find a cheaper flight, in which case we want to cancel the original flight whilst keeping the taxi and booking the cheaper flight. In this case we notify our intentions to the transaction manager who ensures that the more expensive flight is compensated when the LLT completes.




In this blog post I’ve introduced the concept of a compensation-based transaction and showed how it could be used to provide strong guarantees in situations that are not applicable for ACID transactions.



Most of what is discussed here is already supported through our WS-BA implementation. We are currently in the process of decoupling this technology from Web Services and improving the developer API.

Comment by going to Community

Create a new document in JBoss Transactions Development at Community