Lesson 15 of 19
17. Transactions and Locking

Practice: five levels

3 min read+10 XP

Assignments

Five levels. Do them in order. Answers are in "Solutions" at the end, so try first.

Level 1: Think (no code)

A. Name the problem.

  1. Two fans book the last ticket; the event shows −1 seats left.
  2. A report reads an order's total twice in one transaction and gets two different numbers.
  3. "Check no booking exists for seat 14, then insert" sells seat 14 twice.
  4. Two transactions each wait for a row the other has locked; both hang until one is killed.
  5. A cache-refresh lock expired during a long pause, and two workers wrote different values.

B. Pessimistic lock, optimistic lock, atomic update, or a unique constraint? One line each.

  1. Decrement seats_left for a general-admission event.
  2. Prevent two bookings of the same numbered seat.
  3. A user editing their profile in a form for several minutes.
  4. Moving ₹200 between two wallet rows in the same database.

Level 2: Calculate

  1. Every booking locks the single events row for 50 ms. What's the maximum bookings per second for that event?
  2. 100 seats are held for 10 minutes; 30% of holds are abandoned. How many seats come back after the first wave? If holds were 30 minutes, roughly how long would those seats sit unsellable?
  3. A 2PC transaction has 3 participants. How many messages does the coordinator send in a successful run (prepare and commit)?
  4. With optimistic locking, 1,000 users try to book 100 seats at the same instant, each retry taking 20 ms. Roughly how many failed attempts happen in the first round?

Level 3: Build

In Python:

  1. Show the lost update with two interleaved read-modify-writes, and fix it with an atomic UPDATE ... WHERE seats_left > 0 in sqlite3: 130 attempts for 100 seats must sell exactly 100.
  2. A VersionedRow with compare_and_set(expected_version, new_value), and an optimistic booking function with retries.
  3. find_deadlock(waits_for) that finds a cycle in a wait-for graph.
  4. A Seats class with hold_seat(seat, user, now) (10-minute expiry) and confirm(seat, user, now).
  5. A run_saga(steps) that runs compensations in reverse when a step fails.

Level 4: Debug

The signing sold seat 14 to two people. The booking code:

python
  1. Find the bug. Walk through how two requests both succeed.
  2. Fix it so the database itself makes double booking impossible.

Level 5: Design

Design booking for the signing: 100 numbered seats at ₹499, opening at 10:00, with about 20,000 fans trying in the first minute, and separate seat, payment and ticket services.

Deliver:

  1. The seat data model and how a hold is made atomically.
  2. How payment and ticket issuing are coordinated across services, and what happens on each failure.
  3. How expired holds are released.
  4. How you stop 20,000 people from hammering the database at 10:00.
  5. Which isolation level and locking approach you use where.