This question is fundamental to understand when a Transaction Manager is useful for your application.
I think the best way to answer the question is a simple example.
You have a web store application to sell some products: it's a recent application developed for the web.
You have a warehouse application: it's a legacy application you developed some times ago.
The recent web store application uses PostgreSQL, the legacy warehouse application uses Oracle database server.
Until yesterday the web store application passed warehouse update to the warehouse application using a batch process: the web store application produced a file with all the orders, the warehouse application consumed the file to update the warehouse (I mean, this is not perfect, but it's just an example!)
Today the boss is knocking your door and asking: "Can we update the warehouse state every time something is sold?".
The answer must be: "Yes, we can" (you already know it!).
There's a naive approach to the problem: creating a program that updates both PostgreSQL and Oracle at the same time.
I'm using a supposed intuitive syntax to show the flow:
The happy path works fine: for every order there's an update in PostgreSQL database and an update in Oracle database.
If step 6 failed, COMMIT_TRANSACTION(PostgreSQL) returned an error, you could change step 7 as below:
If step 6 completed without errors and step 7 failed, how could you fix the issue?
Unfortunately the first transaction "COMMIT_TRANSACTION(PostgreSQL)" completed and it probably fired some business action like "package something and send to the customer": you would not be able to back-out (rollback) that operation because it was confirmed.
The answer to this question is compensating transaction, but you will discover it could be very difficult to develop simple and clean code using compensating transactions.
The issue becomes harder and harder adding a question like: "What happens if the application will crash while it's in the middle of steps 6 and 7?"
Historically, there's a standard solution, it's name is two phase commit.
We can rewrite the flow in a different way:
Easy enough?
We substituted two distinct START_TRANSACTION with only one START_GLOBAL_TRANSACTION and we substituted two distinct COMMIT_TRANSACTION with only one COMMIT_GLOBAL_TRANSACTION.
Where's the trick? Where's the issue?
Neither PostgreSQL nor Oracle gives you a
START_GLOBAL_TRANSACTION(PostgreSQL, Oracle)
or
COMMIT_GLOBAL_TRANSACTION(PostgreSQL, Oracle)
equivalent verb. Both give you these verbs:
START_TRANSACTION(Mydatabasetype)
COMMIT_TRANSACTION(Mydatabasetype)
you do need a Transaction Manager to perform Distributed Transaction Processing.
LIXA is an XA compliant Transaction Manager able to coordinate Distributed Transaction Processing between your Application Program and some Resource Managers (PostgreSQL and Oracle in the above example).
Using the TX standard the flow of our program becomes:
This is a pointer to the full specification: Distributed TP: The TX (Transaction Demarcation) Specification
You generally don't have to use two phase commit just because you can use two phase commit.
In the past two phase commit was proposed as a generic solution, valid for every type of problem; this is not true, especially because:
But two phase commit can elegantly and effectively solve complex issues when data consistency between distinct databases is a must have condition.
Potentially every process could support two phase commit (from e-mail to fax server), but practically two phase commit support has been developed only for some type of middlewares: databases, message oriented middlewares and something else.
The list of the Resource Managers available to LIXA managed Application Programs is available at FAQ: Frequently Asked Questions.