A dirty read is reading a draft over someone’s shoulder
Draft = uncommitted write, send = COMMIT, delete = ROLLBACK. Only a sent message is a promise.
Safe if the writer commits?
Bad: Only rollbacks hurt
The writer committed, so whatever you read became true.
Good: You saw the middle
Savings debited, wallet not yet credited: you sum ₹3,000, a total no commit ever held.
Two ways to keep an in-flight debit out of sight
Locking makes the reader wait for the writer to end. MVCC hands it the last committed version at once.
PostgreSQL accepts READ UNCOMMITTED, and SHOW transaction_isolation even prints it.
The trap
You get READ COMMITTED. Under MVCC, readers never wait for writers, so dirty reads buy nothing. MySQL and SQL Server really read dirty.
SQL Server reports queue behind writers
Bad: Add WITH (NOLOCK)
No waiting, but never-committed values, and rows read twice or skipped.
Good: Turn on RCSI
Readers get committed versions without shared locks. You pay for a version store.
A rider is assigned to an order that never existed
The order service published OrderPlaced before COMMIT, then rolled back. Isolation levels describe one database; events and cache writes leak around them.
The fix: nothing leaves before COMMIT
- Write the event as an outbox row, same transaction
- A relay publishes committed rows; consumers must be idempotent
- Commit first, then delete the cache key
Remember
A dirty read acts on uncommitted work. Run at READ COMMITTED or higher, clear caches after COMMIT, and publish events through an outbox.