Lab 07: Transactions & Isolation Levels

Time: 40 minutes | Level: Practitioner | DB: PostgreSQL 15 + MySQL 8.0

Transactions ensure data consistency (ACID). Isolation levels define what concurrent transactions can see of each other's uncommitted work — and the anomalies they prevent.


Step 1 — Setup: Bank Accounts

-- PostgreSQL
CREATE TABLE bank_accounts (
  id      SERIAL PRIMARY KEY,
  owner   VARCHAR(50),
  balance NUMERIC(12,2) CHECK (balance >= 0)
);

INSERT INTO bank_accounts (owner, balance) VALUES
  ('Alice', 5000.00),
  ('Bob',   3000.00);

SELECT * FROM bank_accounts;

📸 Verified Output:

 id | owner | balance
----+-------+---------
  1 | Alice | 5000.00
  2 | Bob   | 3000.00
(2 rows)

Step 2 — Basic Transaction: COMMIT and ROLLBACK

📸 Verified Output:

💡 PostgreSQL automatically aborts the transaction on any error — any further commands return ERROR: current transaction is aborted. You must ROLLBACK before starting a new transaction.


Step 3 — Isolation Levels: Overview

Level
Dirty Read
Non-Repeatable Read
Phantom Read

READ UNCOMMITTED

Possible

Possible

Possible

READ COMMITTED

No

Possible

Possible

REPEATABLE READ

No

No

Possible

SERIALIZABLE

No

No

No

Anomaly definitions:

  • Dirty Read: Read uncommitted data from another transaction

  • Non-Repeatable Read: Same query returns different rows within a transaction

  • Phantom Read: Re-running a range query returns new rows inserted by another transaction

💡 PostgreSQL doesn't actually implement READ UNCOMMITTED (it uses READ COMMITTED as minimum). MySQL InnoDB implements all four levels.


Step 4 — READ COMMITTED (Default)


Step 5 — REPEATABLE READ

💡 PostgreSQL uses MVCC (Multi-Version Concurrency Control) — each transaction sees a consistent snapshot of the data as it was at the start. No shared read locks needed.


Step 6 — SERIALIZABLE Isolation


Step 7 — SELECT FOR UPDATE / SELECT FOR SHARE

📸 Verified Output:

Locking options:

Option
Blocks
Allows

FOR UPDATE

Other FOR UPDATE, FOR SHARE, writers

Other readers

FOR SHARE

Other FOR UPDATE, writers

Other FOR SHARE

FOR NO KEY UPDATE

Other FOR UPDATE

FOR SHARE

FOR KEY SHARE

FOR UPDATE only

FOR SHARE, FOR NO KEY UPDATE


Step 8 — Capstone: Optimistic vs Pessimistic Locking

📸 Verified Final State:


Summary

Isolation Level
Default In
Prevents

READ UNCOMMITTED

MySQL (not in PG)

Nothing

READ COMMITTED

PostgreSQL, MySQL

Dirty reads

REPEATABLE READ

MySQL default

Dirty + non-repeatable reads

SERIALIZABLE

All anomalies

Locking
Type
Use When

SELECT FOR UPDATE

Pessimistic

Always consistent, low concurrency

SELECT FOR SHARE

Pessimistic

Read-then-decide, block writers

Version column

Optimistic

High concurrency, retries acceptable

Last updated