[매일메일CS] 동시성 제어와 공유 락(Shared Lock), 배타 락(Exclusive), 데드락(Deadlock)

Euiyeon Park·2025년 7월 31일
0

매일메일 CS

목록 보기
2/3
post-thumbnail

공유 락과 배타 락에 대해서 설명해주세요.

동시성 제어와 락(Lock)

♻️동시성 제어(Concurrency Control)

  • 동시성 제어란 여러 트랜잭션에 동시에 같은 데이터베이스에 접근할 때,
    데이터의 정합성과 일관성을 보장하는 기법
  • 데이터베이스는 성능을 위해 동시 처리(병행 실행)를 최대한 허용하지만,
    동시에 실행되면 문제가 발생할 수 있음

대표적인 동시성 문제1 - Dirty Read

  • 다른 트랜잭션이 아직 커밋하지 않은 변경 데이터를 읽음
  • 만약 T1이 롤백한다면, T2가 읽은 var = 100은 존재하지 않는 값이 되버림

대표적인 동시성 문제2 - Non-Repeatable Read

  • 한 트랜잭션에서 같은 데이터를 두 번 읽을 때 값이 다름
  • 첫 번째 SELECT와 두 번째 SELECT 사이에 다른 트랜잭션이 값을 변경

대표적인 동시성 문제3 - Phantom Read

  • 조건에 맞는 행의 개수나 집합이 바뀜
  • 첫 번째 SELECT 후 다른 트랜잭션이 INSERT하여 두 번째 SELECT 결과가 달라짐

락(Lock)의 필요성

  • 트랜잭션 간 동시 접근으로 인한 데이터 충돌을 방지
  • DBMS는 동시성과 일관성 사이의 균형을 유지
    • 락을 너무 강하게 걸면 → 동시성이 떨어져 성능 저하
    • 락을 너무 약하게 걸면 → 데이터 정합성이 깨짐
  • 필요한 데이터 범위와 작업 성격에 따라 락을 선택적으로 걸어줌

🔒락의 두 가지 기본 형태

공유 락(S Lock, Shared Lock)

  • 읽기 전용 락
  • 여러 트랜잭션이 동시에 같은 데이터에 공유 락을 걸 수 있음
  • 공유 락이 걸린 데이터에 쓰기(UPDATE/DELETE)는 불가능
  • 주로 SELECT .. LOCK IN SHARE MODE 같은 읽기 작업에서 사용
T1: SELECT * FROM account WHERE id = 1 LOCK IN SHARE MODE;  	-- S Lock 획득
T2: SELECT ... LOCK IN SHARE MODE;                          	-- 가능
T3: UPDATE account SET balance = 0 WHERE id = 1;             	-- 대기

쓰기 락(X Lock, Exclusive Lock)

  • 읽기/쓰기 모두 차단하는 락
  • 해당 데이터는 오직 락을 가진 트랜잭션만 읽고 쓸 수 있음
  • 주로 UPDATE, DELETE, INSERT, 또는 SELECT ... FOR UPDATE 시 걸림
  • 데이터 정합성을 위해 읽기조차 막음(Dirty Read 방지)

💡SELECT .. FOR UPDATE는 트랜잭션에서 SELECT한 행에 대해 배타 락을 거는 문법으로
읽는 동시에 그 행을 수정할 권리를 독점(즉, SELECT 한 뒤에 UPDATE 할거야!)

T1: UPDATE account SET balance = 0 WHERE id = 1;   				-- X Lock 획득
T2: SELECT ... LOCK IN SHARE MODE;                 				-- 대기
T3: UPDATE account SET balance = 100 WHERE id = 1;			 	-- 대기

⏳ 락과 데드락의 관계

  • 락(Lock)은 동시성 제어를 위해 필요하지만, 잘못 사용되면
    서로가 서로의 락을 기다리는 교착 상태(Deadlock)를 만들 수 있음
  • 데드락은 두 개 이상의 트랜잭션이 서로가 보유한 자원을 기다리며 무한 대기에 빠지는 상황
T1: account.id = 1 행의 S Lock → 그 다음 account.id = 2 행을 X Lock 하려고 함
T2: account.id = 2 행의 S Lock → 그 다음 account.id = 1 행을 X Lock 하려고 함

데드락 해결/예방 방법1 - 트랜잭션 설계 단계에서 예방

  • 항상 동일한 순서로 자원을 잠금(락 획득 순서를 일관적으로 정해둠)
    (Ex. 모든 트랜잭션에서 1번 데이터, 2번 데이터 순으로 락을 획득)
  • 트랜잭션을 최소화 해 락을 오래 점유하지 못하도록 함
  • 조건절 최적화, 범위 줄이기를 통해 불필요한 락 범위 줄이기

데드락 해결/예방 방법2 - DB 설정으로 완화

  • Lock Timeout 설정 : 일정 시간 기다렸다가 락이 안풀리면 ROLLBACK
  • 격리 수준 낮추기 : READ COMMITED나 MVCC를 활용해 불필요한 대기 감소

데드락 해결/예방 방법3 - 데드락 감지&자동 해제

  • InnoDB, PostgreSQL, Oracle 등 대부분 DB는 주기적으로 데드락 감지 스레드가 돌아감
  • 감지 시 둘 중 하나의 트랜잭션을 강제 ROLLBACK

NEXT STEP

트랜잭션에 대해서 더 깊게 학습이 필요하다 ..!

profile
"개발자는 해결사이자 발견자이다✨" - Michael C. Feathers

0개의 댓글