CS지식/데이터베이스 (Database)

(데이터베이스) Lock, Two-Phase Locking(2PL), 데드락 정리(예제 포함)

불광동 물주먹 2025. 5. 21. 00:28

 데이터베이스 Lock과 2PL, 데드락까지 완벽 정리

동시성을 제어하는 건 단순히 commit을 잘하는 걸 넘어서, **일관성, 격리성(ACID 중 I)**을 유지하는 핵심 기술입니다. 이 포스팅에선 Read/Write Lock, 2PL, 데드락, 그리고 MVCC까지 단계적으로 정리해봅니다.


📌 1. Lock 호환성 (Lock Compatibility)

DB는 트랜잭션 간의 충돌을 막기 위해 Lock을 사용합니다.


 

  read-lock write-lock
read-lock ✅ 가능 ❌ 불가능
write-lock ❌ 불가능 ❌ 불가능
 
  • read-lock (공유 잠금):
    • 다른 트랜잭션이 읽는 것은 가능, 쓰는 것은 불가
    • 여러 트랜잭션이 동시에 읽는 것 가능
  • write-lock (배타 잠금):
    • 읽기/쓰기 둘 다 막음
    • 오직 단일 트랜잭션만 접근 가능

📌 2. Lock 시나리오 예시

✅ 시나리오 1: 두 트랜잭션이 동시에 같은 데이터를 읽을 때

-- Tx1
BEGIN;
SELECT * FROM accounts WHERE id = 1; -- read-lock 획득

-- Tx2
BEGIN;
SELECT * FROM accounts WHERE id = 1; -- read-lock 가능 (공유)

✔ 문제 없이 동시 수행 가능


❌ 시나리오 2: 읽기 중 누군가가 쓰려고 할 때

-- Tx1
BEGIN;
SELECT * FROM accounts WHERE id = 1; -- read-lock

-- Tx2
BEGIN;
UPDATE accounts SET balance = 1000 WHERE id = 1; -- write-lock 시도 → 대기

 

🛑 Tx2는 Tx1의 read-lock이 해제될 때까지 대기
(락 경합 발생)


❌ 시나리오 3: 쓰기 중 다른 트랜잭션이 읽거나 쓰려고 할 때

-- Tx1
BEGIN;
UPDATE accounts SET balance = 1000 WHERE id = 1; -- write-lock

-- Tx2
BEGIN;
SELECT * FROM accounts WHERE id = 1; -- read-lock 시도 → 대기

-- Tx3
UPDATE accounts SET balance = 2000 WHERE id = 1; -- write-lock 시도 → 대기
 
 

🛑 둘 다 write-lock 해제 전까지 대기
→ write-lock은 모든 접근을 차단


📌 3. Two-Phase Locking (2PL)

트랜잭션이 serializable 스케줄을 따르기 위한 기본 원칙.

구조

  1. 확장 단계 (Expanding Phase)
    • Lock만 획득. 해제는 금지.
  2. 축소 단계 (Shrinking Phase)
    • Lock 해제만 가능. 새 Lock 획득 금지.
Tx1: Lock(A) → Lock(B) → Unlock(A) → Unlock(B) ✅ 2PL
Tx2: Lock(A) → Unlock(A) → Lock(B) ❌ 2PL 위반

📌 4. 데드락 (Deadlock)

두 트랜잭션이 서로가 가진 자원을 기다리며 무한 대기하는 상태.

예시

-- Tx1
BEGIN;
LOCK TABLE A; -- A lock
-- 잠시 후
LOCK TABLE B; -- B lock 요청

-- Tx2
BEGIN;
LOCK TABLE B; -- B lock
-- 잠시 후
LOCK TABLE A; -- A lock 요청

 

🌀 Tx1은 B를, Tx2는 A를 기다리며 서로를 기다리는 교착 상태


📌 5. 데드락 해결 전략

방법 설명
타임아웃 일정 시간 초과하면 강제 rollback
Wait-for 그래프 대기 그래프 생성 → 사이클 감지 시 한 트랜잭션 종료
Lock 순서 고정 항상 A → B → C 순으로 Lock 획득 (순서 고정)
 

📌 6. 2PL의 종류 및 특성 비교


종류 설명
Conservative 2PL 트랜잭션 시작 전에 필요한 모든 Lock 미리 획득. 데드락 없음. 비효율적.
Strict 2PL write-lock은 commit/rollback 시점에 반환. Recoverable 보장.
Strong Strict 2PL read/write-lock 모두 commit/rollback 시점에 반환. 구현 쉬우나, Lock 오래 잡음.
 

📌 7. MVCC 소개 (간략)  *다음 파트에서 자세히 설명.

Lock 기반 방식은 성능 병목의 원인이 됩니다. 이를 해결하는 방식이 바로 **MVCC (Multi Version Concurrency Control)**입니다.

  • 데이터를 수정할 때마다 버전을 새로 생성
  • 읽기 트랜잭션은 자신에게 일관된 Snapshot을 보고
  • 쓰기 트랜잭션은 충돌 여부만 체크
  • 대표 DBMS: PostgreSQL, Oracle, MySQL(InnoDB)

→ read/write 간 충돌을 줄여 성능과 동시성 모두 확보


🧠 마무리 요약

항목 설명
read-lock 다중 읽기 허용, 쓰기 차단
write-lock 읽기/쓰기 모두 차단
2PL Lock은 먼저 다 얻고, 해제는 나중에
데드락 서로가 필요한 Lock을 잡고 무한 대기
MVCC 버전 관리로 read/write 충돌 해결