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