[기본 지식] 데드락, 트랜잭션 격리 레벨, 트랜잭션 락

이재훈·2024년 12월 9일
0

1. DB 데드락 (Deadlock)

데드락이란 두 개 이상의 트랜잭션이 서로 상대방이 갖고 있는 자원을 기다리며 무한히 대기하는 상황을 말한다.

예시

  • 트랜잭션 A는 테이블 1에 대한 락을 얻고, 동시에 테이블 2에 대한 락을 요청한다.
  • 트랜잭션 B는 테이블 2에 대한 락을 얻고, 동시에 테이블 1에 대한 락을 요청한다.

이 경우 트랜잭션 A는 트랜잭션 B가 가진 테이블 2 락을 기다리고, 트랜잭션 B는 트랜잭션 A가 가진 테이블 1 락을 가지게 된다. 결국 두 트랜잭션은 서로 상대방의 락을 기다리면서 진행되지 않으며, 데드락 상태에 빠진다.

해결 방법:

  • 타임아웃 설정 : 일정 시간이 지나면 자동으로 트랜잭션을 취소하고, 해당 트랜잭션을 롤백하여 데드락을 해결할 수 있다.
  • 데드락 탐지 : 데이터베이스는 주기적으로 데드락 상태를 검사하고, 이를 감지하면 트랜잭션을 강제로 롤백한다.
  • 트랜잭션 설계 개선 : 락을 순차적으로 획득하는 방식으로 트랜잭션을 설계하여 데드락을 방지할 수 있다.

2. 트랜잭션 격리 레벨 (Transaction Isolation Levels)

트랜잭션 격리 레벨은 데이터베이스에서 여러 트랜잭션이 동시에 실행될 때, 한 트랜잭션 다른 트랜잭션에 의해 영향을 받지 않도록 보장하는 정도를 설정하는 것이다. 트랜잭션 격리 수준은 크게 4가지로 나뉜다.

1. READ UNCOMMITTED (가장 낮은 격리 레벨)

  • 다른 트랜잭션이 아직 커밋하지 않은 데이터를 읽을 수 있다.
  • 문제점 : "더티 리드"가 발생할 수 있다. 이는 다른 트랜잭션이 아직 커밋하지 않은 데이터를 읽는 상황으로, 데이터가 잘못된 상태일 수 있다.

2. READ COMMITTED

  • 다른 트랜잭션이 커밋한 데이터만 읽을 수 있다.
  • 문제점 : "비반복적 읽기"가 발생할 수 있다. 한 트랜잭션 내에서 동일한 쿼리를 두 번 실행했을 때 결과가 달라질 수 있다. 예를 들어, 다른 트랜잭션이 데이터를 수정하고 커밋했기 때문에, 두 번째 조회에서 다른 값이 반환될 수 있다.

3. REPEATABLE READ

  • 한 트랜잭션 내에서 읽은 데이터는 다른 트랜잭션이 수정할 수 없다. 즉, 같은 데이터를 여러 번 읽을 때 같은 결과가 보장된다.
  • 문제점 : "팬텀 리드"가 발생할 수 있다. 트랜잭션이 데이터를 읽을 때, 다른 트랜잭션이 새로운 데이터를 추가하는 경우, 첫번째 트랜잭션에서 두번째 조회 시 새로운 데이터가 포함될 수 있다.

4. SERIALIZABLE (가장 높은 격리 레벨)

  • 모든 트랜잭션이 직렬화된 방식으로 처리되어, 하나의 트랜잭션이 완료될 때까지 다른 트랜잭션이 실행되지 않는다.
  • 장점 : 완벽하게 동시성 문제가 해결된다.
  • 단점 : 성능이 저하된다. 동시에 실행되는 트랜잭션이 많을 경우 처리 속도가 느려질 수 있다.

3. 트랜잭션 락 (Transaction Locks)

트랜잭션 락은 데이터베이스에서 여러 트랜잭션이 동시에 같은 데이터를 변경하지 않도록 보호하는 매커니즘이다. 락은 데이터가 동시성을 처리할 수 있게 하며, 동시에 여러 트랜잭션이 동일한 데이터를 수정하려고 할 때 충돌을 방지한다.

락 종류

공유 락 (Shared Lock)

  • 데이터를 읽을 수는 있지만, 다른 트랜잭션이 해당 데이터를 수정할 수 없도록 한다.여러 트랜잭션이 데이터를 동시에 읽을 수는 있지만, 수정은 불가능하다.

배타적 락 (Exclusive Lock)

  • 데이터를 읽고 수정할 수 있으며, 다른 트랜잭션은 이 데이터를 읽거나 수정할 수 없다. 트랜잭션이 완료될 때까지 해당 자원에 대한 모든 접근이 차단된다.

낙관적 락 (Optimistic Locking)

  • 데이터를 읽은 후, 트랜잭션을 커밋할 때 다른 트랜잭션이 데이터를 수정하지 않았는지 확인한다. 만약 수정이 있었다면, 충돌을 해결하고 다시 시도할 수 있다.
  • 주로 version 컬럼을 사용하여 트랜잭션 충돌을 관리한다.

정리

  • "데드락"은 두 트랜잭션이 서로 상대방의 락을 기다리며 무한히 대기하는 상태를 의미한다. 이를 해결하려면 타임아웃 설정이나 데드락 탐지 기능을 활용해야 한다.
  • "트랜잭션 격리 레벨"은 여러 트랜잭션이 동시에 실행될 때 데이터 일관성을 유지하는 방법을 정의한다. 높은 격리 레벨일수록 성능이 저하될 수 있지만, 더 강한 일관성을 제공한다.
  • "트랜잭션 락"은 트랜잭션 간 충돌을 방지하기 위한 방법이다. 락을 적절히 관리하지 않으면 성능 문제가 발생할 수 있다.

보통의 트랜잭션 격리 레벨은 "READ COMMITTED"로 설정하는 경우가 많다. 이는 대부분의 데이터베이스에서 기본값으로 설정되는 격리 레벨이기도 하며, 일반적으로 적절한 성능과 데이터 일관성의 균형을 맞추기 때문이다.

profile
부족함을 인정하고 노력하자

0개의 댓글