A database transaction is a sequence of operations performed as a single logical unit of work. Either all operations within the transaction are executed successfully, or none of them are. This ensures data consistency and integrity, especially in concurrent environments.
These four properties are often referred to by the acronym ACID.
A transaction typically begins with a command to explicitly start it. The syntax varies depending on the database system.
-- Example SQL: START TRANSACTION;
-- Example SQL: BEGIN TRANSACTION;
If all operations within the transaction are successful and the desired state is reached, the transaction is committed. This makes the changes permanent.
-- Example SQL: COMMIT;
If an error occurs, or if the transaction needs to be undone for any reason, it can be rolled back. This discards all changes made since the transaction began.
-- Example SQL: ROLLBACK;
Let's delve deeper into the ACID properties:
Imagine transferring money between two bank accounts. This involves debiting one account and crediting another. Atomicity ensures that either both operations complete successfully, or neither does. If the credit fails, the debit is rolled back, preventing money loss.
A transaction must preserve database invariants. For example, if a table has a constraint that the sum of account balances must always be positive, a transaction that would violate this would be rejected.
Databases provide different isolation levels (e.g., Read Uncommitted, Read Committed, Repeatable Read, Serializable) to control how transactions interact. The goal is to prevent issues like dirty reads, non-repeatable reads, and phantom reads.
Once a transaction is committed, the database manager ensures that the changes are written to non-volatile storage (like disk) and will survive system restarts. This is often achieved through mechanisms like transaction logs.
Without transactions, an incomplete order (e.g., stock decremented but order not recorded) could lead to significant business problems.
Most programming languages and database connectors provide APIs for managing transactions. You'll typically see methods like:
beginTransaction()
commit()
rollback()
Error handling is paramount. Always wrap your transactional code in try-catch blocks to ensure proper rollback in case of exceptions.