6주차 Unit 4.4 — DB Lock 개념

Psj·5일 전

F-lab

목록 보기
197/230

Unit 4.4 — DB Lock 개념

F-LAB JAVA · 6주차 · Phase 4 · Connection Pool과 DB 세션
🏆 Phase 4 완주 — DB 동시성, 4주차와 만나는 지점


📌 학습 목표

이 Unit을 끝내면 다음을 답할 수 있어야 한다.

  • DB Lock 이 필요한 이유는?
  • 트랜잭션 원자성 보호 와 락의 관계는?
  • 공유 락 (S) 의 동작은?
  • 배타 락 (X) 의 동작은?
  • S/X 호환성 표는?
  • 4주차 자바 synchronized 와 닮음 은?
  • 데드락 은?
  • DB 락 모니터링/해제 는?
  • Phase 4 전체 의 종합은?

🎯 핵심 한 문장

DB Lock 은 여러 세션이 같은 데이터를 동시에 수정해서 트랜잭션 원자성이 깨지는 것을 막기 위해 필요하며, 읽기용 공유 락 (S) 은 여러 세션이 동시에 가질 수 있지만 쓰기용 배타 락 (X) 은 한 세션만 가질 수 있는 점이 4주차 자바 synchronized 락과 닮았고, 두 트랜잭션이 서로의 락을 기다리면 데드락이 발생한다.
락이 필요한 이유는 — 세션1 이 데이터 수정 중 (commit 전) 인데 세션2 가 같은 데이터를 동시에 수정하면 세션1 이 rollback 했을 때 세션2 는 존재하지 않을 데이터 를 수정한 셈이 되어 트랜잭션 원자성이 깨지기 때문이다.
해결책은 트랜잭션 진행 중에는 다른 세션이 해당 데이터를 수정 못 하도록 락 을 거는 것이다.
락 종류는 (1) 공유 락 (S, Shared) — 읽기용, 여러 세션이 동시 보유 가능, (2) 배타 락 (X, eXclusive) — 쓰기용, 한 세션만 보유 가능이다.
이 구조는 4주차의 자바 synchronized 와 닮아 있고 — DB 도 두 트랜잭션이 서로의 락을 기다리는 데드락 이 발생할 수 있어 DB 가 감지·해결한다.

비유 — 도서관 열람실 책 접근

DB Lock = 도서관 책 접근:

락 필요 (원자성 보호):
  - 책에 메모 중 (트랜잭션 A)
  - 다른 사람이 동시에 메모 (트랜잭션 B)
  - 충돌, 누구 메모인지 모름

공유 락 (S, 읽기):
  - 여러 사람 동시 읽기 OK
  - 책 보기만 (수정 X)
  - S + S 호환

배타 락 (X, 쓰기):
  - 메모 중엔 다른 사람 못 봄
  - 한 사람만 점유
  - X 시 다른 락 X

호환 표:
       S    X
  S    OK   대기
  X    대기  대기

자바 synchronized:
  - synchronized 도 한 스레드만
  - 배타 락과 유사
  - 단, DB 는 행/테이블 단위

데드락:
  A: 책1 메모 중, 책2 대기
  B: 책2 메모 중, 책1 대기
  - 서로 기다림 (deadlock)
  - DB 가 감지·하나 해제

→ DB Lock = 원자성 보호 (S/X), 4주차 synchronized 와 닮음, 데드락 가능.


🧭 9개 섹션 로드맵

1. 락이 필요한 이유
2. 트랜잭션 원자성 보호
3. 공유 락 (S)
4. 배타 락 (X)
5. 락 호환성
6. 4주차 synchronized와 닮음
7. 데드락
8. 락 모니터링/해제
9. Phase 4 완주 정리

1️⃣ 락이 필요한 이유

1.1 동시 수정 문제

동시 수정 문제:

  세션1: 데이터 수정 중 (commit X)
  세션2: 같은 데이터 동시 수정

  → 충돌
  → 데이터 무결성 깨짐

1.2 원자성 위험

원자성 위험:

  세션1 rollback 하면:
    - 세션1 의 변경 사라짐
    - 세션2 는 사라진 데이터 수정?
    - → 잘못된 데이터 수정

→ 원자성 위반

1.3 해결 — 락

해결 — 락:

  트랜잭션 중:
    - 다른 세션 수정 막음
    - 락 보유

→ 격리 보장

1.4 동시성 vs 일관성

동시성 vs 일관성:

  락 없으면:
    - 동시성 ↑
    - 일관성 ↓ (위험)

  락 있으면:
    - 일관성 ↑
    - 동시성 ↓ (대기)

→ 균형

1.5 ILIC 의 맥락

-- 락 필요 시나리오 (ILIC)

-- 세션1 (배송 상태 변경 중)
BEGIN;
UPDATE shipments SET status = 'SHIPPED' WHERE id = 1;
-- commit 안 함

-- 세션2 (같은 배송 동시 변경 시도)
BEGIN;
UPDATE shipments SET status = 'CANCELLED' WHERE id = 1;
-- 락 없으면: 충돌, 어느 게 최종?
-- 락 있으면: 세션2 대기 (세션1 commit/rollback 까지)

-- 세션1 rollback 하면:
ROLLBACK;
-- 세션2: 락 풀림, CANCELLED 진행

-- → 락이 원자성 보호

1.6 자기 점검 답변

DB Lock 이 필요한 이유는?

:
1. 동시 수정:

  • 같은 데이터 충돌
  1. 원자성 위험:

    • rollback 시 무결성
  2. 해결:

    • 락으로 격리
  3. 균형:

    • 동시성 vs 일관성

2️⃣ 트랜잭션 원자성 보호

2.1 원자성

원자성 (Atomicity):

  트랜잭션 = 하나의 단위:
    - 전부 성공 또는 전부 실패
    - 중간 상태 X

→ Phase 6.2 에서 상세

2.2 락이 보호하는 것

락이 보호하는 것:

  트랜잭션 진행 중:
    - 변경된 데이터
    - 아직 commit X
    - 다른 세션 못 보거나 못 수정

→ 임시 상태 격리

2.3 격리 수준

격리 수준 (Phase 6.4 예고):

  READ UNCOMMITTED:
    - 락 약함
    - Dirty Read 허용

  READ COMMITTED:
    - 커밋된 것만

  REPEATABLE READ:
    - 반복 일관

  SERIALIZABLE:
    - 가장 엄격

→ 락이 격리 수준 구현

2.4 락의 범위

락의 범위:

  - 행 락 (Row Lock): 한 행
  - 페이지 락: 페이지 단위
  - 테이블 락: 테이블 전체
  - 갭 락: 범위 (InnoDB)

→ 작을수록 동시성 ↑

2.5 ILIC 의 맥락

-- 원자성 보호 (ILIC)

-- 트랜잭션 A: 배송 상태 + 운임 갱신
BEGIN;
UPDATE shipments SET status = 'SHIPPED' WHERE id = 1;
-- ↑ shipments.id=1 에 배타 락
UPDATE freights SET amount = 1000 WHERE shipment_id = 1;
-- ↑ freights 의 해당 행에 배타 락

-- 동시 다른 트랜잭션:
-- 같은 행 수정 시도 → 대기
-- 같은 행 조회 (격리 수준 따라):
--   - REPEATABLE READ: 이전 값
--   - SERIALIZABLE: 대기

COMMIT;
-- 락 해제, 다른 트랜잭션 진행

-- → 트랜잭션 A 동안:
--    "두 UPDATE 가 한 단위" 보장 (원자성)

2.6 자기 점검 답변

트랜잭션 원자성 보호와 락의 관계는?

:
1. 원자성:

  • 한 단위 작업
  1. 락 보호:

    • 임시 상태 격리
  2. 격리 수준:

    • 락 강도
  3. 범위:

    • 행/페이지/테이블

3️⃣ 공유 락 (S)

3.1 공유 락

공유 락 (S, Shared Lock):

  읽기용 락:
    - 여러 세션 동시 보유
    - 읽기 일관성 보장
    - 다른 세션 수정 막음

3.2 동작

공유 락 동작:

  세션1: SELECT (S 락)
  세션2: SELECT (S 락) — OK (호환)
  세션3: UPDATE (X 락) — 대기

→ 읽기는 동시, 쓰기는 막음

3.3 사용 예

-- 명시적 공유 락 (MySQL InnoDB)
BEGIN;
SELECT * FROM shipments WHERE id = 1 LOCK IN SHARE MODE;
-- 또는 (SQL 표준)
SELECT * FROM shipments WHERE id = 1 FOR SHARE;
-- 공유 락 획득 (읽기, 다른 읽기 OK, 쓰기는 대기)

3.4 자동 획득

자동 획득:

  격리 수준 따라:
    - REPEATABLE READ: 일부 자동
    - SERIALIZABLE: SELECT 도 S 락

→ DB 가 자동

3.5 ILIC 의 맥락

-- 공유 락 (ILIC)

-- 운임 계산 (배송 정보 일관 읽기)
BEGIN;
SELECT * FROM shipments WHERE id = 1 FOR SHARE;   -- S 락
-- 다른 세션도 SELECT FOR SHARE OK (같이 읽기)
-- 다른 세션 UPDATE 시도 → 대기

-- 운임 계산
SELECT weight, distance FROM shipment_details WHERE shipment_id = 1;

-- 운임 저장
-- ...

COMMIT;
-- S 락 해제

-- → 계산 중 다른 세션이 수정 못 함 (일관성)
-- → 다른 세션이 같이 읽기는 가능 (성능)

3.6 자기 점검 답변

공유 락 (S) 의 동작은?

:
1. 공유 락:

  • 읽기용
  1. 동작:

    • 여러 세션 동시
    • 쓰기 막음
  2. 사용:

    • FOR SHARE
  3. 자동:

    • 격리 수준 따라

4️⃣ 배타 락 (X)

4.1 배타 락

배타 락 (X, eXclusive Lock):

  쓰기용 락:
    - 한 세션만 보유
    - 다른 모든 락 차단
    - 독점

4.2 동작

배타 락 동작:

  세션1: UPDATE (X 락)
  세션2: SELECT — 대기 (격리 수준 따라)
  세션3: UPDATE — 대기

→ 한 세션만 독점

4.3 자동 획득

자동 획득:

  쓰기 SQL 시:
    - UPDATE → X 락
    - DELETE → X 락
    - INSERT → X 락 (행)

→ 자동

4.4 명시적

-- 명시적 배타 락
BEGIN;
SELECT * FROM shipments WHERE id = 1 FOR UPDATE;
-- X 락 (다른 세션 SELECT FOR UPDATE / UPDATE 대기)

-- 데이터 확인 후 수정
UPDATE shipments SET status = 'SHIPPED' WHERE id = 1;
COMMIT;

4.5 ILIC 의 맥락

-- 배타 락 (ILIC)

-- 시나리오: 재고 차감 (동시성 위험)
BEGIN;
SELECT stock FROM warehouse_items WHERE id = 1 FOR UPDATE;
-- X 락 (다른 세션 같은 행 수정 대기)

-- 재고 확인
-- stock = 10

-- 차감
UPDATE warehouse_items SET stock = stock - 5 WHERE id = 1;
-- stock = 5

COMMIT;
-- X 락 해제

-- 다른 세션이 동시에 같은 작업 시:
-- → 대기 → 첫 세션 commit 후 진행
-- → 재고 중복 차감 방지 (원자성)

4.6 자기 점검 답변

배타 락 (X) 의 동작은?

:
1. 배타 락:

  • 쓰기용
  1. 동작:

    • 한 세션 독점
  2. 자동:

    • UPDATE/DELETE 등
  3. 명시:

    • FOR UPDATE

5️⃣ 락 호환성

5.1 호환성 표

S (다른 세션)X (다른 세션)
현재 SOK (호환)대기
현재 X대기대기

5.2 S + S = OK

S + S = OK:

  두 세션 모두 읽기:
    - 충돌 X
    - 동시 가능
    - 일관성 유지

→ 읽기 동시성

5.3 S + X / X + S = 대기

S + X 또는 X + S = 대기:

  읽기 중 쓰기:
    - 데이터 변경 위험
    - 대기

  쓰기 중 읽기:
    - 미완 데이터 위험
    - 대기

→ 격리

5.4 X + X = 대기

X + X = 대기:

  두 세션 쓰기:
    - 충돌 위험 (최대)
    - 대기

→ 순차 처리

5.5 ILIC 의 맥락

락 호환성 (ILIC)

시나리오:
  세션1: UPDATE shipments WHERE id=1 (X 락)
  
  세션2 시도:
    - SELECT WHERE id=1 — 격리 수준 따라 (대부분 OK, 이전 값)
    - SELECT FOR SHARE — 대기 (S vs X)
    - SELECT FOR UPDATE — 대기 (X vs X)
    - UPDATE WHERE id=1 — 대기 (X vs X)

  세션1: COMMIT
    - 락 해제
    - 세션2 진행

  세션1: UPDATE id=2
    - 다른 행 (X 락 별개)
    - 세션2 의 id=1 작업과 무관

→ 행 단위 락 (행 다르면 동시 가능)

5.6 자기 점검 답변

S/X 호환성 표는?

:
1. S+S:

  • OK
  1. S+X / X+S:

    • 대기
  2. X+X:

    • 대기
  3. 원리:

    • 쓰기 충돌 방지

6️⃣ 4주차 synchronized와 닮음

6.1 닮은 점

DB 락 ↔ synchronized:

  공통:
    - 동시 접근 제어
    - 한 번에 한 주체 (배타)
    - 다른 주체 대기
    - 충돌 방지

6.2 비교 표

항목synchronizedDB Lock
대상자바 객체DB 행/페이지/테이블
주체스레드세션 (트랜잭션)
종류배타만S/X
해제블록 종료commit/rollback

6.3 4주차 가시성/원자성

4주차 가시성/원자성:

  자바: 멀티스레드 + 공유 변수
    - synchronized
    - volatile
    - Atomic

  DB: 멀티세션 + 공유 데이터
    - Lock
    - 격리 수준
    - 트랜잭션

→ 같은 문제, 다른 계층

6.4 5주차 싱글톤 빈

5주차 싱글톤 빈 동시성:

  싱글톤 빈 + 멀티스레드:
    - 4주차 도구 (Atomic, volatile)

  DB + 멀티세션:
    - DB 락
    - 트랜잭션

→ 모든 계층에 동시성 문제

6.5 ILIC 의 맥락

// 닮음 (ILIC)

// 자바 락 (싱글톤 빈, 4주차)
@Service
public class ShipmentCounter {
    private final AtomicLong count = new AtomicLong();   // 4주차 CAS
    
    public void increment() {
        count.incrementAndGet();   // 자바 락 (스레드 안전)
    }
}

// DB 락 (트랜잭션, 6주차)
@Service
public class ShipmentService {
    @Transactional
    public void decrementStock(Long itemId, int amount) {
        // SELECT FOR UPDATE (배타 락)
        // UPDATE stock = stock - ?
        // → DB 락 (세션 간 안전)
    }
}

// → 동시성 = 모든 계층 (스레드, 세션)
// → 닮은 원리, 다른 계층

6.6 자기 점검 답변

4주차 자바 synchronized 와 닮음은?

:
1. 공통:

  • 동시 접근 제어
  1. 차이:

    • 객체 vs 행, 스레드 vs 세션
  2. 4주차 연결:

    • 가시성/원자성
  3. 모든 계층:

    • 동시성 문제

7️⃣ 데드락

7.1 데드락

데드락 (Deadlock):

  두 트랜잭션이 서로의 락 대기:
    - 무한 대기
    - 진행 불가

→ DB 가 감지·해제

7.2 발생 예

데드락 발생:

  트랜잭션 A:
    - shipments.id=1 락 (점유)
    - bookings.id=10 락 대기
  
  트랜잭션 B:
    - bookings.id=10 락 (점유)
    - shipments.id=1 락 대기

  → 서로 대기 (무한)

7.3 DB 의 감지

DB 의 감지:

  주기적 검사:
    - 대기 그래프 (Wait-for graph)
    - 순환 감지

  감지 시:
    - 한 트랜잭션 강제 rollback
    - 다른 트랜잭션 진행

→ 자동 해결

7.4 예방

데드락 예방:

  - 일정한 순서로 락 획득
    (예: 항상 id 작은 것부터)
  - 짧은 트랜잭션
  - 적절한 격리 수준
  - SELECT FOR UPDATE 신중

7.5 ILIC 의 맥락

// 데드락 위험 (ILIC)

// ❌ 위험: 순서 다름
@Service
public class TransferService {
    
    @Transactional
    public void transfer1(Long from, Long to) {
        // from 먼저 락, to 나중
        accountDao.lock(from);   // SELECT FOR UPDATE
        accountDao.lock(to);
    }
    
    @Transactional
    public void transfer2(Long from, Long to) {
        // to 먼저 락, from 나중 (순서 반대)
        accountDao.lock(to);
        accountDao.lock(from);
    }
    // transfer1(A→B) + transfer2(B→A) 동시 → 데드락
}

// ✓ 안전: 일정한 순서
@Service
public class SafeTransferService {
    @Transactional
    public void transfer(Long from, Long to) {
        Long first = Math.min(from, to);   // 항상 작은 ID 먼저
        Long second = Math.max(from, to);
        accountDao.lock(first);
        accountDao.lock(second);
        // → 데드락 X (순서 일정)
    }
}
class AccountDao { void lock(Long id) {} }

7.6 자기 점검 답변

데드락은?

:
1. 데드락:

  • 서로 락 대기
  1. 발생:

    • 순환 대기
  2. DB 감지:

    • Wait-for graph, rollback
  3. 예방:

    • 일정한 순서

8️⃣ 락 모니터링/해제

8.1 락 확인 (MySQL)

-- 락 확인 (MySQL InnoDB)

-- 현재 락 (8.0+)
SELECT * FROM performance_schema.data_locks;

-- 대기 중인 락
SELECT * FROM performance_schema.data_lock_waits;

-- 트랜잭션
SELECT * FROM information_schema.innodb_trx;

8.2 락 해제

락 해제:

  자동:
    - commit
    - rollback
    - 세션 종료

  강제:
    - KILL 세션 ID
    - 운영자

8.3 락 타임아웃

락 타임아웃:

  innodb_lock_wait_timeout (MySQL):
    - 기본 50초
    - 초과 시 자동 rollback
    - "Lock wait timeout exceeded"

→ 무한 대기 방지

8.4 운영 팁

운영 팁:

  - 긴 트랜잭션 모니터링
  - 락 대기 알람
  - 데드락 로그 확인
  - SELECT FOR UPDATE 신중
  - 격리 수준 조정

8.5 ILIC 의 맥락

-- 락 모니터링 (ILIC MySQL)

-- 현재 락 상태
SELECT 
    OBJECT_NAME, INDEX_NAME, LOCK_TYPE, LOCK_MODE, LOCK_STATUS
FROM performance_schema.data_locks
WHERE OBJECT_NAME LIKE 'shipments';

-- 락 대기
SELECT 
    r.trx_id AS waiting_trx,
    r.trx_query AS waiting_query,
    b.trx_id AS blocking_trx,
    b.trx_query AS blocking_query
FROM information_schema.innodb_lock_waits w
JOIN information_schema.innodb_trx r ON r.trx_id = w.requesting_trx_id
JOIN information_schema.innodb_trx b ON b.trx_id = w.blocking_trx_id;

-- 문제 트랜잭션 강제 종료
KILL <trx_id>;

-- 설정 확인
SHOW VARIABLES LIKE 'innodb_lock_wait_timeout';

8.6 자기 점검 답변

DB 락 모니터링/해제는?

:
1. 모니터링:

  • performance_schema
  1. 해제:

    • commit/rollback/KILL
  2. 타임아웃:

    • innodb_lock_wait_timeout
  3. 운영:

    • 긴 TX 알람

9️⃣ Phase 4 완주 정리

9.1 Phase 4 학습 종합

Phase 4 — Connection Pool과 DB 세션

Unit 4.1 — 매 요청 연결 비효율
  - TCP/인증/세션 비용
  - 본말전도

Unit 4.2 — Connection Pool ★깊이
  - 미리 N 개, 재사용
  - HikariCP

Unit 4.3 — DB 세션과 연결
  - Connection ↔ Session 1:1
  - 풀 N = 세션 N

Unit 4.4 — DB Lock
  - S/X 락
  - 4주차 연결, 데드락

9.2 핵심 메시지

Phase 4 핵심 메시지:

  "DB 연결은 비싸므로 Connection Pool 로
   N 개 미리 만들고 재사용한다.
   풀의 Connection 은 DB 세션과 1:1 매핑되며,
   세션 간 충돌은 락으로 막는다."

9.3 다음 Phase 예고

Phase 4 → Phase 5:
  - Connection 비용/구조 → 추상화

Phase 5 — DataSource (5.3 ★깊이):
  - 다양한 커넥션 획득 방식
  - 추상화 필요성
  - DataSource 인터페이스 ★깊이
  - DriverManagerDataSource

9.4 면접 단골 질문 매핑

Q핵심 답변
락 이유?원자성 보호
공유 락?읽기, 여러 세션
배타 락?쓰기, 한 세션
호환성?S+S OK, X 단독
synchronized 닮음?동시 접근 제어
데드락?서로 락 대기
예방?일정한 순서
타임아웃?innodb_lock_wait_timeout
모니터링?performance_schema
행 락?InnoDB

9.5 추가 심화 질문

Q1: 낙관적 락 vs 비관적 락?

답:

  • 비관적: 락 미리 (충돌 가정)
  • 낙관적: version 컬럼 (커밋 시 확인)
  • 충돌 적으면 낙관적
  • JPA @Version

Q2: 트랜잭션 격리 수준?

답:

  • READ UNCOMMITTED ~ SERIALIZABLE
  • 락 강도 조절
  • Phase 6.4 상세
  • 동시성 vs 일관성

Q3: 분산 락?

답:

  • 여러 서버 간 락
  • Redis, Zookeeper
  • DB 락은 단일 DB 만
  • 마이크로서비스

Q4: 락 에스컬레이션?

답:

  • 행 락 너무 많아지면
  • 페이지/테이블 락 승격
  • DB 가 자동
  • 동시성 ↓

Q5: MVCC?

답:

  • Multi-Version Concurrency Control
  • 읽기에 락 X (버전 보임)
  • InnoDB/PostgreSQL
  • 읽기-쓰기 충돌 ↓

🎯 핵심 요약 — 3줄 정리

1. DB Lock 의 필요성

  • 동시 수정 시 원자성 깨짐 방지 (rollback 시 무결성)
  • 공유 락 (S, 읽기) / 배타 락 (X, 쓰기)

2. 4주차 synchronized 와 닮음

  • 동시 접근 제어 (객체↔행, 스레드↔세션)
  • 락 = 모든 계층의 동시성 해결 원리

3. 데드락

  • 서로 락 대기 → 무한 대기
  • DB 가 감지·rollback, 예방은 일정한 순서

🏆 Phase 4 완주 — Connection Pool과 DB 세션

🔗 Phase 4 — Connection Pool과 DB 세션
  ✅ Unit 4.1 매 요청마다 연결의 비효율
  ✅ Unit 4.2 Connection Pool ★깊이
  ✅ Unit 4.3 DB 세션과 연결 구조
  ✅ Unit 4.4 DB Lock 개념 ← 여기, Phase 4 완주

→ 연결 비용 (TCP/인증/세션)
→ 풀 (재사용, HikariCP)
→ Connection ↔ Session 1:1
→ 락 (원자성 보호, 4주차 연결)

📚 다음으로...

Phase 5 — DataSource 인터페이스 (5.3 ★깊이)

💾 Phase 5 — DataSource 인터페이스
  Unit 5.1 — 다양한 커넥션 획득 방식
  Unit 5.2 — 추상화 필요성
  Unit 5.3 — DataSource 인터페이스 ★깊이
  Unit 5.4 — DriverManagerDataSource

6주차 누적 진행

🧪 Part A (9 Unit) ✅
💾 Part B — DB 접근의 진화
  ✅ Phase 3 — JDBC (3)
  ✅ Phase 4 — Connection Pool (4) ← 완주
  ⏭ Phase 5 — DataSource (4, 5.3 ★깊이)

총: 16/28 Unit

🏆 Phase 4 완주 — Connection Pool과 DB 세션

profile
Software Developer

0개의 댓글