| << 17.1.0- Understanding Transactions | Chapter17 | 17.1.2- Writing Transactional Applications >> |
What is a Transaction?
A transaction is an atomic unit of work that either fails as a whole or succeeds as a whole. It is particularly useful in scenarios like the cash transfer that we've just described, where the completion of a single task involves the successful execution of a number of related but separate actions – and that the failure of any one or more actions will cause an inconsistency or a similar problem.
So a transaction can be made up of multiple actions, and if each part of the transaction is successful then the transaction itself is successful. By contrast, if any one part of the transaction fails (or if more than one part of the transaction fails), then the entire transaction will be marked as failed. When a transaction is marked as 'failed', the system will automatically return everything back to the state that it was in before the transaction was started – by undoing all the changes that the system had made since the beginning of the transaction. The process of undoing changes is known as rollback.
For example, consider our cash transfer transaction, which involves two separate but related actions – one updates a database table to reflect a deduction in one account balance, and the other updates the database to reflect a credit to another account balance. If either the deduction or the credit parts of the transaction fail then all changes made by the transaction will be rolled back. The transaction will only complete successfully if all of the composite parts complete successfully. The following table demonstrates this:
|
|
Credit part succeeds |
Credit part fails |
|
Deduction part succeeds |
Outcome = success: all parts of the transaction have succeeded, so the changes made by the transaction are committed |
Outcome = rollback: one part of the transaction has failed, so all changes made by the transaction are undone |
|
Deduction part fails |
Outcome = rollback: one part of the transaction has failed, so all changes made by the transaction are undone |
Outcome = rollback: two parts of the transaction have failed, so all changes made by the transaction are undone |
Voting for Success or Failure
How does the transaction decide whether it has succeeded or failed? As we said, we can divide the transaction up into different parts, each of which takes care of a different action. Then, we give each action the opportunity to vote on whether or not it has completed successfully and satisfactorily:
- If the action succeeds, then it can register a vote for 'completion'
- If the action fails, then it can register a vote for 'failure'
But there's an extra point to note here: as you might have expected, the voting system in a transaction requires a unanimous consensus. The transaction will only succeed if all of its constituent parts succeeded – a majority verdict is not enough to allow the transaction to succeed! If any part of the transaction registers a vote for 'failure', then the transaction as a whole must fail.
The ACID Properties
We've talked about the notion of a transaction guaranteeing that the application maintains a consistent state. But we can define a transaction more precisely than that. In fact, a transaction is an action or group of actions that demonstrates four very particular characteristics – atomicity, consistency, isolation and durability (collectively known by the acronym ACID). In order for a set of related actions to form a true transaction, they must exhibit all four characteristics. Let's have a look at them now.
Atomicity
A transaction is atomic – which refers to the 'one-ness' of the constituent parts of the transaction. The transaction atomicity guarantees that the constituent parts of the transaction are completed either all together or not at all. If the transaction makes updates to the system, then they too should be completed entirely (if the transaction is voted to be successful) or rolled back to their original state (if any part of the transaction registered a vote for failure). If the transaction breaks down in the middle, then the atomicity property will ensure that everything that occurred before the breakdown will be rolled back to its original state.
Let's consider how our cash transfer transaction is atomic. The transaction is in two parts – a deduction from account A followed by a credit to account B. So as we saw above, if there's a power failure after the money was deducted from account A, then the 'credit' part of the transaction will be deemed to have failed. Then, the system will roll the transaction back, returning the deducted amount to account A and hence returning the system to its original state.
Consistency
A transaction enforces consistency in the system state, by ensuring that the system is in a valid state at the end of any completed or failed transaction. If the transaction completes successfully then its consistency is a guarantee that all changes to the system will have been made properly, and the system is in a valid state. If the transaction fails then any changes already made will automatically be rolled back (and the original state will be resumed); and since the system was in a consistent state when the transaction was started, it will once again be in a consistent state.
Let's look again at the account transfer system: one measure of consistency in the system is to note that the total of the balances of all the accounts does not change – the bank does not have a license to create money, and we certainly don't want any money to disappear. If an error occurs in a cash transfer, all parts of the transaction are rolled back and the total of all balances remains the same as before. If the transaction completes, then an equal sum has been deducted from one account and added to another account: the total of all balance remains the same, and the system as a whole retains its consistency.
Isolation
A transaction is isolated, which means that the transaction runs in isolation from other transactions and processes that might be going on around it. Thus, at the time the transaction is running, it runs in the belief that it has exclusive use of the system – it thinks that it is the only action that the system is carrying out at that time.
This is important, because the state of the system may not be consistent during the execution of a transaction (the consistency property ensures that the system is consistent at the beginning and end of a transaction, but not necessarily during the transaction). If one transaction accesses inconsistent data that exists as a result of the fact that there's currently another transaction running, then we'll get problems. Isolation avoids this by prohibiting the possibility that two transactions may run concurrently.
Here's an example of how isolation might be useful in our banking application. Suppose that you had exactly $200 in your account, and that you'd written two checks, each for $100.00. Suppose also that these checks were being processed at exactly the same moment by two different bank tellers. If the checks were processed concurrently, then each bank teller would note the initial balance of $200, each would deduct $100 from that and each would return a final balance of $100. But in fact, the final balance should be $0. By enforcing isolation, the transactions would automatically be scheduled to run one-after-another, and this error would not occur.
Durability
A transaction is durable in that, once it has been successfully completed, all of the changes it made to the system are permanent. There are safeguards that will prevent the loss of information, even in the case of system failure. By logging the steps that the transaction performs, the state of the system can be recreated even if the hardware itself has failed. The concept of durability allows the developer to know that a completed transaction is a permanent part of the system, regardless of what happens to the system later on.
How does our cash transfer transaction demonstrate durability? By writing the results of the transaction to the bank's data store.
| << 17.1.0- Understanding Transactions | Chapter17 | 17.1.2- Writing Transactional Applications >> |

RSS

