Session A reads and holds the range, Session B attempts a priority 25 INSERT, Session C updates job_id 103, and Session O observes the post-COMMIT result.
MySQL Locking Reads: SELECT ... FOR UPDATE and Next-Key Locks
locking read · next-key interval · data_locksQuestion for this Lab
For the same tenant_id range, how do plain SELECT, FOR UPDATE, and isolation level change the waits for Session B's INSERT and Session C's UPDATE?
The jobs table, idx_tenant_priority_job, tenant_id = 7 range, and result rows job_id 102 and 103 stay fixed.
Executed SQL
SELECT job_id, priority, revision, note
FROM lock_jobs FORCE INDEX (idx_tenant_priority_job)
WHERE tenant_id = 7
AND priority >= 20
AND priority < 40
ORDER BY priority, job_id
FOR UPDATERecord, gap, and next-key locks held by Session A and the B → A and C → A wait edges change by variant.
The range predicate, holder result rows, B and C attempts, and completion after Session A COMMIT stay the same.
Who waits before COMMIT under REPEATABLE READ + SELECT ... FOR UPDATE?
Open the wait-graph step of the RR · FOR UPDATE variant and confirm who waits for what before Session A commits.
- Where do you look?
- Read each wait edge in the trace corridor together with its indexName, lockMode, and lockData.
- Screen to open
RR · FOR UPDATE · wait graph
What should you see?
This variant has two wait edges. Session C's job_id 103 UPDATE waits on the PRIMARY row lock, and Session B's priority 25 INSERT waits on the gap preceding LOCK_DATA (7, 30, 103) in idx_tenant_priority_job. Both are recorded before Session A COMMIT.
Evidence boundary- Captured
- C → A and B → A wait edges from data_lock_waits with their lock attributes
Checkpoint · explain from evidenceHow do the captured wait edges differ across the three variants?Reveal answer and basis
rr-plain has no wait edge. rr-for-update has both C → A and B → A. rc-for-update retains only the C → A row wait. Waiting statements complete after Session A COMMIT.
Evidence boundary- Captured
- per-variant wait edges from data_lock_waits
A locking read can protect index records and preceding gaps, while the isolation level changes range protection that blocks an INSERT.
This Lab closes the eight-Lab path from access paths through row versions to lock waits. Finish by comparing it directly with the preceding consistent-read Lab.
Review terms
record lockIntroduced in Lab 08- A lock on a specific index record that makes conflicting updates or locking reads wait.
gap lockIntroduced in Lab 08- A lock that protects the interval between index records and can conflict with an INSERT into that interval.
next-key lockIntroduced in Lab 08- An InnoDB lock form that combines an index-record lock with the gap preceding that record to protect a range.
lock waitIntroduced in Lab 08- A state where a statement pauses because its requested lock conflicts with an incompatible lock held by another transaction.
READ COMMITTEDIntroduced in Lab 07- An isolation level where each consistent read uses a fresh snapshot as of the start of that statement.
It reads task rows where tenant_id = 7 and priority is at least 20 and below 40.
Session A locks the matched rows and the index gap between them, so both the job_id 103 UPDATE and job_id 106 INSERT wait for COMMIT.
Run the same SELECT in three conditions and compare whether Session B's INSERT and Session C's UPDATE run immediately or wait for COMMIT.
- Current condition
- REPEATABLE READ + SELECT ... FOR UPDATE
- Session A
- Session A · runs SELECT
- Session B
- Session B · tries INSERT
- Session C
- Session C · tries UPDATE
Before Session A runs SELECT
The WHERE clause reads lock_jobs rows for tenant_id = 7, then keeps only rows whose priority is at least 20 and below 40.
| tenant_id | priority | job_id |
|---|---|---|
| 7 | 10 | 101 |
| 7 | 20 | 102 |
| 7 | 30 | 103 |
| 7 | 40 | 104 |
| 7 | 50 | 105 |
tenant_id = 7 · priority >= 20 · priority < 40After Session A runs SELECT
Session A reads job_id 102 and 103 and keeps FOR UPDATE locks. Session C waits on the job_id 103 row lock, and Session B waits on the index gap for priority 25.
SELECT ... FOR UPDATE- job_id 102tenant_id 7 · priority 20
- job_id 103tenant_id 7 · priority 30
After Session A commits
After Session A commits, the locks are released and the waiting UPDATE and INSERT complete.
- UPDATED · job_id 103
- INSERTED · job_id 106
| tenant_id | priority | job_id | state |
|---|---|---|---|
| 7 | 20 | 102 | UNCHANGED |
| 7 | 25 | 106 | INSERTED |
| 7 | 30 | 103 | UPDATED |