๐ Guide: Database Transactions, Concurrency, Locking, and Normalization
This guide covers foundational concepts that ensure data integrity, consistency, and performance in transactional systems โ including ACID properties, concurrency control, locking, and data modeling trade-offs between normalization and denormalization.
โ 1. Database Transactions & ACID
A transaction is a unit of work that must be atomic, consistent, isolated, and durable.
๐งช ACID Properties
Property | Description |
---|---|
Atomicity | All steps succeed or none do |
Consistency | Must leave DB in valid state (constraints respected) |
Isolation | Transactions don't interfere with each other |
Durability | Once committed, it remains โ even after crash |
Example: Atomic transfer between accounts
BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
COMMIT;
๐ 2. Concurrency & Isolation Levels
Concurrency allows multiple transactions to run in parallel. To prevent race conditions and anomalies, databases use isolation levels:
Isolation Level | Prevents... | Notes |
---|---|---|
Read Uncommitted | โ Nothing | Fast, unsafe |
Read Committed | โ Dirty Reads | Default in many DBs |
Repeatable Read | โ Non-repeatable Reads | Good for reads |
Serializable | โ Phantom Reads, full isolation | Strict, slowest |
Common concurrency issues:
Issue | Description |
---|---|
Dirty read | Read uncommitted data |
Non-repeatable read | Same query returns different results mid-tx |
Phantom read | New rows appear that match query mid-tx |
Lost update | Overwrite data written by another tx |
๐ 3. Locking Strategies
Locks control access to rows, tables, or ranges.
๐ต Pessimistic Locking
- Locks data before using it
- Prevents conflicts by blocking access
- Slower, may cause contention
-- Example: SELECT ... FOR UPDATE (pessimistic)
BEGIN;
SELECT * FROM accounts WHERE id = 1 FOR UPDATE;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
COMMIT;
๐ข Optimistic Locking
- Assumes no conflict โ verifies before write
- Uses version/timestamp fields
- Great for low-contention scenarios
-- Example: optimistic version check
UPDATE products
SET stock = stock - 1, version = version + 1
WHERE id = 123 AND version = 4;
If 0 rows affected โ retry, conflict detected.
๐ 4. Normalization vs Denormalization
These are two competing strategies for modeling data in relational databases.
๐งช Normalization
- Splits data into multiple related tables
- Reduces redundancy, improves integrity
Example:
Table: Orders | Table: Customers |
---|---|
id, customer_id, ... | id, name, email, ... |
Pros
โ
Smaller storage
โ
Fewer anomalies
โ
Easier to update single source of truth
Cons
โ More joins = slower queries
โ Complex schema evolution
โ Tougher for analytics
๐ฆ Denormalization
- Combines data to reduce joins
- Prioritizes read performance and query simplicity
Example:
Table: Orders |
---|
id, customer_name, customer_email, ... |
Pros
โ
Fewer joins
โ
Faster reads
โ
Simple queries for dashboards
Cons
โ Data duplication
โ Risk of inconsistencies
โ Update anomalies (requires syncing)
๐ Comparison Table
Feature | Normalized | Denormalized |
---|---|---|
Write Performance | Better | Worse (updates touch more) |
Read Performance | Worse (joins) | Better (fewer joins) |
Storage Usage | Efficient | Redundant |
Data Consistency | Strong | Weaker |
Analytics Use | Harder | Easier |
๐ง Bonus: When to Choose What?
Use Case | Recommendation |
---|---|
OLTP (banking, inventory) | โ Normalize |
OLAP (dashboards, BI) | โ Denormalize |
Mixed workloads | ๐ค Hybrid (views, materialized tables) |
๐ Further Reading
- PostgreSQL Transaction Docs
- SQL Isolation Levels Explained
- Optimistic vs Pessimistic Locking (Baeldung)
- Normalization Forms (1NF to 5NF)
- Martin Kleppmann - CRDTs, Transactions, and Concurrency
<< back to Guides