Modern applications constantly read and modify data. Banks transfer money between accounts, online stores reduce inventory after purchases, social networks save posts and comments, and airline systems reserve seats for passengers. Behind all of these operations is a database responsible for keeping information accurate and consistent. ๐ป๐
But what happens if something goes wrong halfway through an operation?
Imagine a banking system transferring $500 from one account to another. The database subtracts $500 from the sender’s account, but before it adds the money to the recipient’s account, the server suddenly crashes.
Without protection, the money could simply disappear.
Database systems prevent problems like this using transactions.
A database transaction groups one or more operations into a single logical unit of work. The database ensures that either the entire transaction succeeds or its incomplete changes are undone.
This principle helps prevent corrupted, inconsistent, or partially updated data even when applications crash, multiple users make changes simultaneously, or hardware failures occur. ๐ง โ๏ธ
๐ What Is a Database Transaction?
A transaction is a sequence of database operations treated as one complete action.
Suppose an online store receives an order.
The database may need to:
- Create the order record
- Reduce product inventory
- Record the payment status
- Add shipping information
- Update the customer’s purchase history
These steps are logically connected.
If only some of them succeed, the database could become inconsistent.
For example, imagine inventory is reduced but the order itself is never created. The store would appear to have fewer products available even though no valid order exists.
A transaction allows all of these operations to be treated together.
Conceptually:
Begin transaction โก๏ธ Perform operations โก๏ธ Verify success โก๏ธ Commit
If something fails:
Begin transaction โก๏ธ Perform operations โก๏ธ Error occurs โก๏ธ Roll back
The transaction therefore acts like a protective boundary around related changes. ๐ก๏ธ
โ What Does COMMIT Mean?
When every operation inside a transaction succeeds, the application can issue a COMMIT.
A commit tells the database:
“These changes are complete and should become permanent.”
For example:
BEGIN;
UPDATE accounts
SET balance = balance - 500
WHERE id = 1;
UPDATE accounts
SET balance = balance + 500
WHERE id = 2;
COMMIT;
Once committed, the transfer is considered successfully completed.
The database ensures that the transaction’s changes are preserved according to its durability mechanisms.
โฉ๏ธ What Is a ROLLBACK?
If something goes wrong before the transaction is committed, the database can perform a ROLLBACK.
A rollback reverses the incomplete changes made during that transaction.
For example:
BEGIN;
UPDATE accounts
SET balance = balance - 500
WHERE id = 1;
-- An error occurs here
ROLLBACK;
After the rollback, the sender’s balance returns to its original state.
From the perspective of permanent database data, it is as though the failed transaction never happened.
This ability is one of the most important defenses against data corruption.
๐ฆ The Classic Bank Transfer Example
Consider two accounts:
Account A: $2,000
Account B: $1,000
We want to transfer $500 from A to B.
A successful transaction should produce:
Account A: $1,500
Account B: $1,500
The operation contains two critical steps:
- Subtract $500 from Account A.
- Add $500 to Account B.
Without transactions, a crash after step one could leave:
Account A: $1,500
Account B: $1,000
The system has lost $500.
With a transaction, both updates are treated as a single unit.
Either:
Both changes succeed โ
or:
Neither change remains โฉ๏ธ
This is the central idea behind transaction safety.
๐งฑ The ACID Properties
Database transactions are commonly explained using four properties known as ACID:
Atomicity, Consistency, Isolation, and Durability
Together, these properties describe how a reliable transactional database should behave.
โ๏ธ Atomicity: All or Nothing
Atomicity means a transaction behaves as one indivisible operation.
Either every required change is successfully completed or none of the changes are permanently applied.
Consider an order that requires:
- Creating an invoice
- Charging an account
- Reducing inventory
If the inventory update fails, atomicity allows the database to undo the earlier steps.
Conceptually:
Step 1 succeeds โ
Step 2 succeeds โ
Step 3 fails โ
Entire transaction rolls back โฉ๏ธ
Atomicity prevents partial transactions from leaving the database in a broken state.
โ๏ธ Consistency: Data Rules Must Remain Valid
Consistency means a transaction should move the database from one valid state to another valid state while respecting defined rules.
Databases can enforce constraints such as:
- Primary keys must be unique
- Foreign keys must reference valid records
- Required fields cannot be null
- Account balances may have defined restrictions
- Inventory quantities may need to satisfy business rules
Suppose a system requires every order to reference an existing customer.
An attempt to create an order for a nonexistent customer may violate a foreign-key constraint.
The database rejects the invalid modification rather than allowing inconsistent data to remain.
Consistency therefore combines transaction behavior with properly designed database constraints and application logic. ๐งฉ
๐ Isolation: Transactions Should Not Interfere Incorrectly
Databases often serve many users simultaneously.
Imagine two customers attempting to purchase the final item in stock at exactly the same time.
Both transactions might initially read:
Inventory = 1
If both independently decide the item is available and then both reduce inventory, the store could sell the same product twice.
This is a concurrency problem.
Isolation helps prevent simultaneous transactions from interfering with each other in unsafe ways.
Ideally, each transaction behaves as though it is executing alone, even when many transactions are actually happening at the same time.
๐พ Durability: Committed Changes Must Survive
Durability means that once the database confirms that a transaction has committed, its changes should survive failures such as a process crash or power interruption, subject to the guarantees of the database and storage configuration.
Suppose a customer receives:
Payment successful โ
If the server crashes one second later, the payment record should not suddenly disappear.
Database systems use techniques such as transaction logs, persistent storage, checkpoints, replication, and recovery processes to help preserve committed data.
Durability creates confidence that a completed transaction truly stays completed.
๐ Transaction Logs
One of the most important mechanisms supporting transactions is the transaction log.
Before or while modifying actual database pages, many database engines record information about changes in a persistent log.
This is often related to a technique called write-ahead logging, or WAL.
The general principle is:
Record enough information about the change in the log before relying on the modified database page itself.
If the server crashes, the database can inspect the log during recovery.
It may use the log to:
- Redo committed operations
- Undo incomplete operations
- Restore database consistency
The transaction log acts like a detailed record of what the database was trying to accomplish. ๐
โก How Write-Ahead Logging Helps
Imagine a transaction changes an account balance.
The new data may temporarily exist in memory before the modified database page is written to permanent storage.
If power fails immediately, that memory is lost.
With write-ahead logging, the database first ensures that a record describing the change reaches durable storage.
After restarting, the database can consult the log and reconstruct the committed update if necessary.
Conceptually:
Change requested โก๏ธ Log written โก๏ธ Transaction committed โก๏ธ Data pages written
This ordering greatly improves recoverability.
๐ Crash Recovery
Suppose a database server unexpectedly loses power while hundreds of transactions are active.
When it restarts, the database may need to determine:
- Which transactions committed successfully
- Which transactions were incomplete
- Which changes reached disk
- Which committed changes must be reapplied
- Which incomplete changes must be undone
Using its transaction log and recovery algorithms, the database restores itself to a valid state.
Users generally do not need to manually identify every partially completed write.
This automated crash recovery is one reason transactional databases are so reliable.
๐ฅ What Happens When Multiple Users Edit the Same Data?
Concurrency introduces some of the hardest database problems.
Imagine two employees editing the same inventory record.
The original quantity is:
100 units
User A reads 100 and subtracts 10.
User B also reads 100 and subtracts 20.
If their changes are handled poorly:
User A writes:
90
Then User B writes:
80
The final database says 80 units remain.
But 30 units were actually removed, so the correct answer should be:
70
The first user’s update has effectively been lost.
This problem is called a lost update.
Transaction isolation and concurrency-control mechanisms help prevent situations like this.
๐ How Locking Protects Data
One traditional way databases manage concurrency is through locks.
A transaction may obtain a lock on certain data before changing it.
For example:
Transaction A locks row โก๏ธ Updates row โก๏ธ Commits โก๏ธ Releases lock
If Transaction B tries to modify the same row during that time, it may have to wait.
Locks can exist at different levels, such as:
- Row-level
- Page-level
- Table-level
Smaller locks generally allow more concurrency, while larger locks may simplify protection at the cost of blocking more operations.
๐ธ Multi-Version Concurrency Control
Many modern databases use Multi-Version Concurrency Control, commonly abbreviated as MVCC.
Instead of forcing readers and writers to block each other constantly, MVCC can maintain multiple logical versions of data.
For example, one transaction may see an older committed version of a row while another transaction is creating a newer version.
This allows readers to work with a consistent snapshot without necessarily blocking writers.
MVCC is used in major database systems because it can provide strong transaction isolation while supporting high levels of concurrency.
๐ป Dirty Reads
A dirty read occurs when one transaction reads data written by another transaction that has not yet committed.
Suppose:
Transaction A changes a price from $100 to $50.
Before A commits, Transaction B reads the new $50 price.
Then Transaction A encounters an error and rolls back.
The official price returns to $100.
Transaction B has now used a value that never became permanent.
Higher isolation levels can prevent dirty reads by ensuring transactions see only appropriate committed data.
๐ Non-Repeatable Reads
A non-repeatable read occurs when a transaction reads the same row twice but receives different values because another transaction changed the row between the two reads.
For example:
First read: balance = $1,000
Another transaction commits a change.
Second read: balance = $800
Depending on the application, this may be acceptable or problematic.
Database isolation levels determine which kinds of concurrent changes a transaction is allowed to observe.
๐ฅ Phantom Reads
A phantom read involves sets of rows rather than a single row.
Suppose a transaction runs:
SELECT * FROM orders
WHERE total > 1000;
It finds 20 orders.
Another transaction inserts a new qualifying order and commits.
If the first transaction runs the same query again, it might now find 21 rows.
The new row is sometimes called a phantom.
Stronger isolation levels can prevent or control this behavior.
๐๏ธ Database Isolation Levels
SQL databases commonly support several isolation levels.
Exact implementations vary, but common names include:
- Read Uncommitted
- Read Committed
- Repeatable Read
- Serializable
Higher isolation generally provides stronger protection against concurrency anomalies.
However, stronger isolation can also reduce performance by increasing locking, version maintenance, conflict detection, or retries.
Database designers therefore choose isolation levels based on the application’s requirements.
A financial ledger may demand extremely strict consistency, while an analytics dashboard may tolerate slightly older data in exchange for higher throughput.
๐ Serializable Transactions
Serializable isolation aims to make concurrent transactions behave as though they had executed one at a time in some valid sequence.
This provides one of the strongest commonly available isolation guarantees.
Imagine transactions A, B, and C running simultaneously.
A serializable database tries to ensure the final result is equivalent to something like:
A โก๏ธ B โก๏ธ C
or:
B โก๏ธ C โก๏ธ A
even if their actual execution overlaps.
Some systems accomplish this through locking, while others use optimistic concurrency control or detect conflicts and force transactions to retry.
๐ Deadlocks
Locks solve many concurrency problems, but they can create another issue called a deadlock.
Imagine:
Transaction A locks Record 1 and waits for Record 2.
Transaction B locks Record 2 and waits for Record 1.
Neither can proceed.
Conceptually:
Transaction A waits for B ๐
Transaction B waits for A ๐
The database detects the deadlock and usually aborts one transaction so the other can continue.
The aborted transaction may then be retried by the application.
Deadlock handling is an important part of transactional database systems.
๐งฎ Constraints Provide Another Layer of Protection
Transactions are most effective when combined with database constraints.
Common examples include:
๐ Primary Key Constraints
Prevent two rows from using the same unique identifier.
๐ Foreign Key Constraints
Prevent records from referring to related records that do not exist.
๐ซ NOT NULL Constraints
Require certain fields to contain a value.
โ CHECK Constraints
Enforce rules such as:
quantity >= 0
These safeguards help prevent invalid states even when application code contains mistakes.
๐ Transactions in an Online Store
Consider a customer purchasing the final laptop in stock.
The application might perform:
- Verify inventory.
- Reserve one unit.
- Create the order.
- Record payment authorization.
- Update inventory.
- Confirm the transaction.
If step 4 fails, the system may need to undo the inventory reservation and order creation.
Without a transaction, cleanup could become complicated and error-prone.
With transactional logic, related database changes can be committed only when the operation reaches an acceptable state.
๐จ Preventing Double Booking
Reservation systems provide another good example.
Imagine there is only one hotel room available.
Two customers press Book at nearly the same moment.
Without proper transaction isolation:
Customer A sees 1 room available
Customer B sees 1 room available
Both submit reservations.
Now two people believe they own the same room.
A properly designed transaction can lock or conditionally update the availability record so only one reservation succeeds.
The second customer receives a message that the room is no longer available.
Transactions therefore protect not just stored numbers, but real-world business rules. ๐จ๐
๐ง Transactions in Banking
Banking systems rely heavily on transactional guarantees.
Operations may include:
- Deposits
- Withdrawals
- Transfers
- Interest calculations
- Bill payments
- Ledger updates
Financial data cannot safely tolerate arbitrary partial updates.
If a payment is recorded in one ledger but missing from another required record, reconciliation becomes difficult.
Transactions help ensure the database preserves meaningful accounting relationships.
๐ฌ Social Media and Messaging Applications
Transactions are useful even when money is not involved.
Suppose a social network creates a new post and simultaneously updates a user’s post count.
If the post is created but the count update fails, the displayed statistics become inaccurate.
Likewise, a messaging application may need to update:
- Message record
- Conversation metadata
- Unread count
- Delivery status
Transactions help keep related information synchronized.
๐๏ธ Not Every Operation Needs a Huge Transaction
Transactions are powerful, but keeping them open for too long can create problems.
A long transaction may:
- Hold locks
- Increase storage for old row versions
- Block other transactions
- Increase the chance of conflicts
- Make rollback more expensive
Good database design generally keeps transactions as short as practical while still protecting the required logical operation.
For example, an application should usually avoid opening a transaction, waiting several minutes for a user to fill out a form, and then finally committing.
๐ Transactions Across Multiple Services Are Harder
Modern applications are often divided into many services.
An online purchase might involve:
- Order service
- Payment service
- Inventory service
- Shipping service
If each service uses a separate database, one traditional transaction may not easily cover the entire workflow.
Distributed transaction mechanisms exist, including approaches based on two-phase commit, but they add complexity and may affect availability or performance.
Many modern architectures instead use techniques such as:
- Saga patterns
- Compensating transactions
- Idempotent operations
- Event-driven workflows
These methods coordinate consistency across multiple systems without relying on one database transaction spanning everything.
๐ Idempotency Helps Prevent Duplicate Changes
Imagine a payment request is sent over a network, but the application does not receive the response.
It retries the request.
If the original payment actually succeeded, the customer could be charged twice unless the system detects the duplicate.
An idempotent operation is designed so that repeating the same request does not incorrectly apply the effect multiple times.
Transactions and idempotency often work together in reliable distributed systems.
๐ก๏ธ Transactions Do Not Fix Every Kind of Data Error
Transactions protect against many forms of partial updates and concurrency problems, but they cannot guarantee that every value is logically correct.
For example, if an employee accidentally enters:
Price = $10
instead of:
Price = $100
the database can commit that transaction perfectly.
From a transactional perspective, nothing failed.
The data is wrong because the input was wrong.
This is why reliable systems also require:
- Input validation
- Business rules
- Database constraints
- Backups
- Auditing
- Access control
- Monitoring
Transactions are a critical protection layer, but they are part of a larger data-integrity strategy.
๐ฟ Transactions Are Not a Substitute for Backups
Durability helps preserve committed changes, but databases can still be damaged by:
- Hardware failures
- Software bugs
- Accidental deletion
- Malicious activity
- Storage corruption
- Natural disasters
Backups and replication remain essential.
A transaction can protect an individual operation, while backups protect against larger-scale data loss.
Reliable systems use both.
๐ง A Simple Transaction Lifecycle
A typical transaction can be summarized like this:
1. โถ๏ธ BEGIN
The database starts tracking a unit of work.
2. โ๏ธ READ AND WRITE
The application queries and modifies records.
3. ๐ CONCURRENCY CONTROL
Locks, versions, or conflict checks protect interactions with other transactions.
4. โ
VALIDATE
Constraints and database rules are checked.
5. ๐พ COMMIT
The transaction becomes permanent.
Or, if a problem occurs:
5. โฉ๏ธ ROLLBACK
Incomplete changes are discarded.
This simple structure protects an enormous variety of applications.
๐ The Bigger Picture
Database transactions prevent data corruption by ensuring that related operations are handled as carefully controlled units instead of independent, fragile updates.
The core principles are summarized by ACID:
Atomicity โ๏ธ ensures all-or-nothing execution.
Consistency โ๏ธ helps preserve valid database states.
Isolation ๐ prevents concurrent transactions from interfering in unsafe ways.
Durability ๐พ ensures committed changes survive according to the database’s persistence guarantees.
Behind these properties are sophisticated mechanisms such as transaction logs, write-ahead logging, locking, MVCC, constraint enforcement, deadlock detection, rollback, and crash recovery.
Together, they allow databases to remain reliable even while thousands of users perform operations simultaneously.
Whenever you transfer money, reserve a hotel room, place an online order, send a message, or update an account, there is a good chance that database transactions are quietly protecting the information behind the scenes. ๐ฆ๐๐ฌ
They transform a potentially dangerous sequence of independent writes into a controlled operation that either finishes correctly or leaves the database as though the failed attempt never occurred.
That simple guaranteeโcomplete the whole operation or preserve the previous valid stateโis one of the foundations of reliable modern software. ๐๏ธ๐

