공유 락과 배타 락에 대해서 설명해주세요.
동시성 제어와 락(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
트랜잭션에 대해서 더 깊게 학습이 필요하다 ..!