Transactions describe a system’s ability to support tentative or multistep changes. When you make changes within the context of a transaction, the system provides four main guarantees:
To observers not participating in the transaction, the commands inside the transaction have not impacted the system.
Once you decide to finalize (commit) a transaction, either all of the changes take effect or none of them do.
Errors caused during a transaction that would cause an inconsistent system state are dealt with in order to bring the system back to a consistent state.
Once the system has informed you of the transaction’s successful completion, you can be certain that the changes are permanent.
As a real-world example of a transaction, consider a money transfer between two bank accounts. This might happen in two stages: subtract the money from the first account, and then add the money to the second account. In this situation, you have the exact same goals for robustness and correctness:
While the money transfer is taking place (but has not yet completed), the balance of both bank accounts appears unchanged.
At some point in the process, it’s possible that we’ve subtracted the money from the first account but haven’t added it yet to the second account. When we process the money transfer, it’s critical that the system never show this intermediate state. Either all of the changes take effect or none of them ...