트랜잭션 잠금

서버란·2024년 10월 1일

CS 지식

목록 보기
14/25

트랜잭션 잠금은 데이터베이스에서 동시성 제어를 위한 중요한 기법 중 하나입니다

  1. Locking (잠금) 트랜잭션 잠금은 여러 트랜잭션이 동시에 같은 자원(예: 테이블, 행)을 수정하거나 읽으려고 할 때, 데이터 일관성을 유지하기 위해 사용됩니다. 일반적으로 트랜잭션이 데이터에 접근하는 동안 다른 트랜잭션이 해당 데이터에 접근하지 못하도록 잠금(Lock)을 걸어 충돌을 방지합니다.

  2. Deadlock (교착 상태) 두 개 이상의 트랜잭션이 서로의 잠금이 해제되기를 기다리면서 발생하는 문제입니다. 예를 들어 트랜잭션 A가 리소스 X를 잠금하고, 트랜잭션 B가 리소스 Y를 잠금한 상태에서 A가 Y를 요청하고 B가 X를 요청하면, 둘 다 영원히 대기 상태에 빠지는 상황이 발생할 수 있습니다.

  3. Lock Granularity (잠금의 세분성) 잠금은 다양한 수준에서 적용될 수 있습니다. 예를 들어 테이블 전체를 잠글 수도 있고, 특정 행만 잠글 수도 있습니다. 더 작은 단위의 잠금(예: 행 단위)은 동시성을 더 잘 지원하지만, 잠금 관리를 위한 오버헤드가 발생할 수 있습니다. 반대로 큰 단위의 잠금(예: 테이블 단위)은 동시성은 떨어지지만 관리가 더 단순합니다.

  4. Optimistic Locking (낙관적 잠금) 낙관적 잠금은 트랜잭션이 자원을 수정할 때 잠금을 걸지 않고, 수정이 완료되기 직전에 충돌이 발생했는지 확인하는 방식입니다. 충돌이 없을 것이라는 가정 하에 동작하며, 충돌이 발생한 경우 트랜잭션을 롤백하고 다시 시도합니다.

  5. Pessimistic Locking (비관적 잠금) 비관적 잠금은 트랜잭션이 자원을 읽거나 수정하기 전에 미리 잠금을 거는 방식입니다. 충돌 가능성이 높을 것으로 예상되는 경우 이 방식을 사용하여 트랜잭션의 충돌을 미리 방지합니다.

트랜잭션 격리 수준에서 Dirty Read 외에 자주 언급되는 다른 두 가지 문제는 Non-repeatable Read와 Phantom Read입니다. 이 세 가지는 데이터베이스 트랜잭션에서 발생할 수 있는 동시성 문제로, 트랜잭션 격리 수준을 적절히 설정하지 않으면 발생할 수 있는 문제들입니다.

  1. Dirty Read (더티 리드)
    Dirty Read는 트랜잭션 A가 아직 커밋되지 않은 트랜잭션 B의 데이터를 읽는 상황을 말합니다. 만약 트랜잭션 B가 이후에 롤백되면, 트랜잭션 A는 잘못된 데이터를 읽은 셈이 됩니다.

예시:
트랜잭션 A가 트랜잭션 B가 커밋되지 않은 데이터를 읽습니다. 하지만 트랜잭션 B가 이후 롤백된다면, 트랜잭션 A는 유효하지 않은 데이터를 기반으로 작업한 것이 됩니다.

  1. Non-repeatable Read (반복 불가능한 읽기)
    Non-repeatable Read는 한 트랜잭션 내에서 동일한 데이터를 여러 번 읽을 때, 그 데이터가 다른 트랜잭션에 의해 수정되었을 경우 발생하는 문제입니다. 즉, 첫 번째 읽기와 두 번째 읽기의 값이 달라지는 상황입니다.

예시:
트랜잭션 A가 특정 데이터를 읽습니다. 이후 트랜잭션 B가 그 데이터를 수정한 후 커밋합니다. 다시 트랜잭션 A가 같은 데이터를 읽으면, 처음 읽었을 때와 다른 값이 나옵니다.

  1. Phantom Read (팬텀 리드, 유령 읽기)
    Phantom Read는 한 트랜잭션 내에서 같은 쿼리를 여러 번 실행할 때, 다른 트랜잭션에 의해 새로 추가된 데이터가 나타나는 상황을 말합니다. 즉, 첫 번째 쿼리에서는 없던 데이터가 두 번째 쿼리에서 나타나는 현상입니다.

예시:
트랜잭션 A가 SELECT 쿼리로 특정 조건에 맞는 레코드를 조회합니다. 그 후 트랜잭션 B가 새로운 데이터를 삽입하고 커밋합니다. 다시 트랜잭션 A가 같은 조건으로 SELECT 쿼리를 실행하면, 처음에는 없던 새로운 레코드가 나타나게 됩니다.

요약

Dirty Read: 커밋되지 않은 데이터를 읽는 문제.
Non-repeatable Read: 동일한 데이터를 반복해서 읽을 때, 중간에 다른 트랜잭션에 의해 데이터가 변경되어 일관성이 없는 데이터를 읽는 문제.
Phantom Read: 동일한 조건으로 쿼리를 실행할 때, 중간에 다른 트랜잭션에 의해 데이터가 삽입되어 추가적인 행이 나타나는 문제.
이 문제들을 방지하기 위해 데이터베이스는 여러 트랜잭션 격리 수준을 제공합니다. 예를 들어, Serializable 수준은 가장 높은 격리 수준으로 Dirty Read, Non-repeatable Read, Phantom Read 모두를 방지하지만, 성능 저하를 초래할 수 있습니다.


좋습니다! 트랜잭션 격리 수준에 따라 Dirty Read, Non-repeatable Read, Phantom Read 문제를 방지하는 방법에 대한 답을 알려드리겠습니다.

Q1: Non-repeatable Read를 방지할 수 있는 격리 수준은 무엇인가요?

답: Repeatable Read 이상 수준의 격리에서 Non-repeatable Read를 방지할 수 있습니다. Repeatable Read는 트랜잭션이 시작된 후 동일한 데이터를 여러 번 읽을 때, 다른 트랜잭션에서 그 데이터를 변경하지 못하도록 보장합니다. 따라서 같은 트랜잭션 내에서 읽은 값은 항상 동일하게 유지됩니다.

Q2: Phantom Read를 방지하기 위해 데이터베이스 시스템에서는 어떤 메커니즘을 사용할 수 있을까요?

답: Serializable 격리 수준을 사용하면 Phantom Read를 방지할 수 있습니다. Serializable 수준은 트랜잭션들이 일련의 순서대로 직렬화되어 실행되는 것처럼 보이게 만들어, 동일한 조건의 SELECT 쿼리를 여러 번 실행할 때 중간에 다른 트랜잭션이 데이터를 추가하거나 변경할 수 없게 합니다. 이로 인해 Phantom Read 문제가 발생하지 않습니다.

Q3: 각 트랜잭션 격리 수준(READ UNCOMMITTED, READ COMMITTED, REPEATABLE READ, SERIALIZABLE)이 동작하는 방식의 차이점은 무엇인가요?

답:
1. READ UNCOMMITTED:

  • Dirty Read 허용
  • 트랜잭션이 커밋되지 않은 데이터를 읽을 수 있음.
  • 성능은 좋지만, 데이터 일관성이 낮음.
  1. READ COMMITTED:
  • Dirty Read 방지
  • 트랜잭션이 커밋된 데이터만 읽을 수 있음.
  • 하지만 Non-repeatable Read와 Phantom Read는 허용됨.
  1. REPEATABLE READ:
  • Dirty Read와 Non-repeatable Read 방지
  • 동일한 트랜잭션에서 읽은 데이터는 변하지 않음.
  • 하지만 Phantom Read는 여전히 발생할 수 있음.
  1. SERIALIZABLE:
  • Dirty Read, Non-repeatable Read, Phantom Read 모두 방지
  • 트랜잭션들이 일련의 순서대로 실행되는 것처럼 직렬화된 상태로 보장함.
  • 성능 오버헤드가 가장 큼.

이처럼 트랜잭션 격리 수준은 동시성 제어와 데이터 일관성 사이에서 균형을 맞추기 위해 존재하며, 높은 수준의 격리는 더 많은 동시성 문제를 방지하지만, 그만큼 성능에 부담을 줄 수 있습니다.

profile
백엔드에서 서버엔지니어가 된 사람

0개의 댓글