← Home ← Codex ← DEBT ← Engine
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 111
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
2 pings T 0 pings F 0 pings S 1 ping S 1 ping M 0 pings T 0 pings W 2 pings T 1 ping F 1 ping S 0 pings S 1 ping M 0 pings T 0 pings W 1 ping T 0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 3 pings T 2 pings F 0 pings S 0 pings S 0 pings M 1 ping T 0 pings W 1 ping T 1 ping F
Google 1
Ahrefs 1
Scrapy 9 Amazonbot 8 Google 8 Ahrefs 7 Perplexity 7 PetalBot 7 Bing 5 Claude 3 SEMrush 3 Unknown AI 2 Twitter/X 2 Applebot 2 Brave Search 2 Meta AI 1 Qwen 1 Sogou 1
crawler 66 crawler_json 2
🧱 FUNDAMENTALS — new to this? Start with the ground floor.
Database database A database is an organized collection of data stored electronically, designed so programs can efficiently retrieve, add, update, and delete information.

Nearly every application needs to remember information between sessions. Databases provide the reliable, fast, and organized storage that makes persistent data possible at any scale.

💡 Always use prepared statements with placeholders—never concatenate user input directly into database queries.

Ask Codex about Database →
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