개발기록

데이터베이스 트랜잭션과 잠금 메커니즘 이해하기 본문

Spring

데이터베이스 트랜잭션과 잠금 메커니즘 이해하기

Danuvibe 2024. 9. 15. 11:28

데이터베이스 트랜잭션과 잠금 메커니즘은 데이터의 일관성과 동시성을 관리하는 핵심 개념입니다. 이 글에서는 일반 트랜잭션과 읽기 전용 트랜잭션의 차이점, 그리고 각각의 상황에서 잠금이 어떻게 동작하는지 설명하겠습니다.

1. 트랜잭션의 기본 개념

트랜잭션은 데이터베이스의 상태를 변화시키는 하나의 논리적 작업 단위를 말합니다. 트랜잭션은 ACID 속성(원자성, 일관성, 고립성, 지속성)을 보장해야 합니다.

2. 잠금(Lock)의 개념

잠금은 동시성 제어를 위해 사용되는 메커니즘입니다. 여러 트랜잭션이 동시에 같은 데이터에 접근할 때 데이터의 일관성을 유지하기 위해 사용됩니다.

주요 잠금 유형:

  • 공유 잠금(Shared Lock): 읽기 작업에 사용
  • 배타적 잠금(Exclusive Lock): 쓰기 작업에 사용

3. 일반 트랜잭션에서의 잠금 획득

일반 트랜잭션(읽기-쓰기 트랜잭션)에서는 다음과 같은 과정으로 잠금이 이루어집니다:

  1. 트랜잭션 시작
  2. 데이터 읽기 시 공유 잠금 획득
  3. 데이터 수정 시 배타적 잠금으로 업그레이드
  4. 트랜잭션 종료 시 모든 잠금 해제

예시 코드:

@Transactional
public void updateUser(Long userId, String newName) {
    User user = userRepository.findById(userId).orElseThrow();  // 공유 잠금 획득
    user.setName(newName);  // 배타적 잠금으로 업그레이드
    userRepository.save(user);  // 변경사항 저장
}  // 트랜잭션 종료 시 잠금 해제

이 과정에서 일어나는 일:

  1. findById 호출 시 해당 레코드에 대한 공유 잠금 획득
  2. setName 호출로 엔티티 수정 시 배타적 잠금으로 자동 업그레이드
  3. 트랜잭션 종료 시 모든 잠금 해제

4. 읽기 전용 트랜잭션에서의 잠금 획득

읽기 전용 트랜잭션(@Transactional(readOnly = true))에서는 다음과 같은 과정으로 잠금이 이루어집니다:

  1. 트랜잭션 시작
  2. 데이터 읽기 시 공유 잠금 획득 (일부 DB에서는 잠금 없이 진행)
  3. 트랜잭션 종료 시 잠금 해제

예시 코드:

@Transactional(readOnly = true)
public User getUser(Long userId) {
    return userRepository.findById(userId).orElseThrow();  // 공유 잠금 획득 (또는 잠금 없음)
}  // 트랜잭션 종료 시 잠금 해제

이 과정에서 일어나는 일:

  1. findById 호출 시 해당 레코드에 대한 공유 잠금 획득 (DB에 따라 다름)
  2. 데이터 수정 시도 시 예외 발생
  3. 트랜잭션 종료 시 잠금 해제

5. 읽기 전용 트랜잭션의 최적화

많은 데이터베이스 시스템은 읽기 전용 트랜잭션을 최적화합니다:

  1. 잠금 획득 최소화: 일부 DB는 읽기 전용 트랜잭션에 대해 잠금을 완전히 생략
  2. MVCC(Multi-Version Concurrency Control) 활용: 읽기 작업이 쓰기 작업을 차단하지 않음
  3. 읽기 전용 스냅샷: 트랜잭션 시작 시점의 일관된 데이터 뷰 제공

6. 잠금 수준과 격리 수준

트랜잭션의 격리 수준에 따라 잠금의 강도와 지속 시간이 달라집니다:

  • READ UNCOMMITTED: 잠금 사용하지 않음
  • READ COMMITTED: 짧은 기간 동안 읽기 잠금 사용
  • REPEATABLE READ: 트랜잭션 종료까지 읽기 잠금 유지
  • SERIALIZABLE: 가장 강력한 잠금, 완전한 격리 제공

7. 데드락(Deadlock) 주의

잠금을 사용할 때는 데드락에 주의해야 합니다. 데드락은 두 개 이상의 트랜잭션이 서로 상대방이 점유하고 있는 자원을 기다리며 진행되지 못하는 상황을 말합니다.

데드락 예방 방법:

  • 트랜잭션의 크기를 작게 유지
  • 일관된 순서로 잠금 획득
  • 타임아웃 설정

결론

트랜잭션과 잠금 메커니즘은 데이터베이스의 동시성 제어와 데이터 일관성 유지를 위해 중요합니다. 읽기 전용 트랜잭션은 일반 트랜잭션에 비해 더 가벼운 잠금을 사용하거나 잠금을 완전히 생략하여 성능을 최적화합니다. 개발자는 이러한 특성을 이해하고 적절히 활용하여 애플리케이션의 성능과 데이터 무결성을 모두 확보할 수 있습니다.

Comments