← CodeClarityLab Home
Browse by Category
+ added · updated 7d
← Back to glossary

Transaction Isolation Levels

database PHP 5.1+ Advanced
debt(d9/e5/b7/t7)
d9 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'silent in production until users hit it' (d9). The term's detection_hints list only laravel-debugbar and mysql-slow-query-log, neither of which actually detect wrong isolation levels — they show query timing, not concurrency bugs. The code_pattern notes 'phantom reads or non-repeatable reads causing business logic errors' which only manifest under concurrent load. These bugs are nearly impossible to catch with tooling; they appear intermittently in production when multiple transactions race.

e5 Effort Remediation debt — work required to fix once spotted

Closest to 'touches multiple files / significant refactor in one component' (e5). While the quick_fix suggests 'Use READ COMMITTED' as a simple configuration change, fixing isolation-level-related bugs in practice requires understanding which transactions need what guarantees, potentially restructuring transaction boundaries, and adding explicit locking where needed. It's not a one-line fix because you must audit all affected code paths.

b7 Burden Structural debt — long-term weight of choosing wrong

Closest to 'strong gravitational pull' (b7). The term applies to web, cli, and queue-worker contexts — every database interaction is shaped by this choice. Wrong isolation levels create load-bearing assumptions throughout the codebase. Transaction boundaries, retry logic, and concurrent access patterns all depend on understanding the isolation semantics. Changing isolation levels mid-project requires auditing every transactional code path.

t7 Trap Cognitive debt — how counter-intuitive correct behaviour is

Closest to 'serious trap' (t7). The misconception explicitly states 'READ COMMITTED is always safe — it still allows non-repeatable reads.' Common_mistakes reinforce this: developers assume MySQL and PostgreSQL use the same defaults (they don't), or that READ UNCOMMITTED is acceptable. The behavior contradicts what developers expect from 'committed' reads, and the per-session/per-transaction scoping surprises those used to global settings.

About DEBT scoring →

Also Known As

isolation levels database isolation ACID isolation

TL;DR

SQL standards defining how and when changes made by one transaction are visible to others, trading consistency for concurrency.

Explanation

The four standard isolation levels from weakest to strongest: READ UNCOMMITTED (dirty reads allowed), READ COMMITTED (no dirty reads, default in PostgreSQL), REPEATABLE READ (no non-repeatable reads, default in MySQL InnoDB), SERIALIZABLE (full isolation, no phantom reads). Higher isolation prevents more anomalies but increases lock contention. Most applications work correctly with READ COMMITTED; SERIALIZABLE is reserved for financial operations requiring strict consistency.

Diagram

flowchart TD
    subgraph Weakest
        RU[READ UNCOMMITTED<br/>Dirty reads allowed]
    end
    subgraph Mid1
        RC[READ COMMITTED<br/>No dirty reads<br/>PostgreSQL default]
    end
    subgraph Mid2
        RR[REPEATABLE READ<br/>No non-repeatable reads<br/>MySQL default]
    end
    subgraph Strongest
        SR[SERIALIZABLE<br/>No phantom reads<br/>Full isolation]
    end
    RU --> RC --> RR --> SR
    SR -.->|higher isolation = more locking| PERF[Lower Concurrency]
style RU fill:#f85149,color:#fff
style SR fill:#238636,color:#fff
style RC fill:#d29922,color:#fff
style RR fill:#d29922,color:#fff

Common Misconception

READ COMMITTED is always safe — it still allows non-repeatable reads (same row read twice in a transaction returns different values if another transaction commits between reads).

Why It Matters

Wrong isolation level causes phantom reads, non-repeatable reads, or dirty reads — subtle data integrity bugs that only manifest under concurrent load and are nearly impossible to debug after the fact.

Common Mistakes

  • Assuming MySQL and PostgreSQL use the same default — MySQL uses REPEATABLE READ, PostgreSQL uses READ COMMITTED.
  • Using READ UNCOMMITTED in production — dirty reads return data that may be rolled back.
  • SERIALIZABLE on every transaction — massive lock contention; use only where strictly required.
  • Not understanding that isolation level is set per-session or per-transaction, not globally.

Code Examples

✗ Vulnerable
// READ UNCOMMITTED — sees uncommitted data from other transactions:
$pdo->exec('SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED');
$pdo->beginTransaction();
$balance = $pdo->query('SELECT balance FROM accounts WHERE id = 1')->fetchColumn();
// $balance may reflect a transaction that will be rolled back — dirty read
✓ Fixed
// SERIALIZABLE for financial operations:
$pdo->exec('SET TRANSACTION ISOLATION LEVEL SERIALIZABLE');
$pdo->beginTransaction();
try {
    $balance = $pdo->query('SELECT balance FROM accounts WHERE id = 1 FOR UPDATE')->fetchColumn();
    if ($balance >= $amount) {
        $pdo->exec('UPDATE accounts SET balance = balance - ' . $amount . ' WHERE id = 1');
    }
    $pdo->commit();
} catch (Exception $e) { $pdo->rollBack(); throw $e; }

Added 15 Mar 2026
Edited 22 Mar 2026
Views 26
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings F 1 ping S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 1 ping T 0 pings F 2 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 1 ping S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 1 ping S
No pings yesterday
Amazonbot 7 Perplexity 7 Ahrefs 2 Unknown AI 2 Google 1
crawler 19
DEV INTEL Tools & Severity
🟡 Medium ⚙ Fix effort: Medium
⚡ Quick Fix
Use READ COMMITTED for most PHP web applications — it prevents dirty reads without the performance overhead of REPEATABLE READ's gap locks
📦 Applies To
PHP 5.1+ web cli queue-worker
🔗 Prerequisites
🔍 Detection Hints
Phantom reads or non-repeatable reads causing business logic errors; deadlocks from REPEATABLE READ gap locks
Auto-detectable: ✗ No laravel-debugbar mysql-slow-query-log
⚠ Related Problems
🤖 AI Agent
Confidence: Medium False Positives: High ✗ Manual fix Fix: High Context: File Tests: Update
CWE-362

✓ schema.org compliant