Engine Atlas

MySQL 잠금 읽기: SELECT ... FOR UPDATE와 Next-Key Lock

locking read · next-key interval · data_locks
MySQL 8.4.10captured evidence
English

실행 variant
한눈에 보기조회 전 · 대기 · COMMIT 후
요약
C UPDATE + B INSERT 대기
이 쿼리는 뭘 하나요?

tenant_id = 7이고 priority가 20 이상 40 미만인 task row를 조회합니다.

조회 결과job_id 102, 103

Session A가 조회한 row와 그 사이 index gap을 잠그기 때문에 job_id 103 UPDATE와 job_id 106 INSERT가 모두 COMMIT까지 기다립니다.

같은 SELECT를 세 조건으로 실행해서 Session B의 INSERT와 Session C의 UPDATE가 바로 실행되는지, COMMIT을 기다리는지 비교합니다.

현재 비교 조건
REPEATABLE READ + SELECT ... FOR UPDATE
Session A
Session A · SELECT 실행
Session B
Session B · INSERT 시도
Session C
Session C · UPDATE 시도
1

Session A가 SELECT하기 전

WHERE 절은 lock_jobs에서 tenant_id = 7인 row만 보고, 그중 priority가 20 이상 40 미만인 row를 고릅니다.

조회 범위
tenant_idpriorityjob_id
710101
720102
730103
740104
750105
tenant_id = 7 · priority >= 20 · priority < 40
2

Session A가 SELECT한 뒤

Session A는 job_id 102, 103을 읽고 FOR UPDATE lock을 유지합니다. Session C는 job_id 103 row lock에서, Session B는 priority 25를 넣을 index gap에서 기다립니다.

SELECT ... FOR UPDATE
  • job_id 102tenant_id 7 · priority 20
  • job_id 103tenant_id 7 · priority 30
Session C · UPDATE job_id 103
Session A COMMIT까지 대기
Session B · INSERT job_id 106, priority 25
Session A COMMIT까지 대기
3

Session A가 COMMIT한 뒤

Session A가 COMMIT하면 lock이 풀리고 기다리던 UPDATE와 INSERT가 이어서 완료됩니다.

  • UPDATED · job_id 103
  • INSERTED · job_id 106
tenant_idpriorityjob_idstate
720102UNCHANGED
725106INSERTED
730103UPDATED