ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 📂 MySQL - 트랜잭션 격리 수준
    💻 computer science/📦 database 2024. 5. 11. 14:14

    🔝 트랜잭션 격리 수준 🌟

    모든 DB 트랜잭션은 격리수준을 갖고 있어야 한다.

    서버 환경에서는 여러 개의 트랜잭션이 동시에 진행될 수 있다.

    • 적절하게 격리수준을 조정해 가능한 한 많은 트랜잭션을 동시에 진행시키면서도 문제가 발생하지 않게 해야 한다.

     

    🌠 트랜잭션 격리 수준

     

    격리 수준 설명  발생하는 이상 현상
    SERALIZABLE 트랜잭션을 순차적으로 진행

    - 여러 트랜잭션이 동시에 같은 행에 접근할 수 없다.

    - deadlock이 일어날 확률도 높고 성능이 가장 떨어짐 
    REPEATABLE_READ 특정 행을 조회시 항상 같은 데이터를 응답하는 것을 보장하는 격리 수준 하나의 트랜잭션이 수정한 행을 다른 트랜잭션이 수정할 수 없다

    - 새로운 행을 추가하는 것은 막지 않는다. 
    phantom read 
    READ_COMMITTED 다른 트랜잭션이 커밋하지 않은 정보는 읽을 수 없다.

    - 가장 많이 사용되는 격리 수준

    - 커밋이 완료된 데이터에 대해서만 다른 트랜잭션에서 조회를 허용한다.
    phantom read 

    non-repeatable read 
    READ_UNCOMMITTED 하나의 트랜잭션이 커밋되기전에 다른 트랜잭션에 노출된다.

    - 가장 빠르다.

    - 몇몇 행이 정확하게 조회되지 않더라도 괜찮은 많은 양의 데이터를 ‘어림잡아’ 집계하는데 사용하면 좋다.
    phantom read 

    non-repeatable read 


    dirty-read

     

     

    ⚠️ 트랜잭션 격리 수준에서 발생하는 현상

     

    이상 현상 문제
    phantom read 한 트랜잭션 내에서 동일한 쿼리를 보냈을 때 해당 조회 결과가 다른 경우

    ex) 사용자 A가 조회 ⇒ B가 다른 데이터 삽입
    ⇒ 한 트랜잭션 내에서 A가 한번 더 조회시 다른 결과가 조회된다.
    non-repeatable read 한 트랜잭션 내의 같은 행에 두 번 이상 조회가 발생했을 경우 그 결과가 다른 경우

    ex) A가 조회 ⇒ B가 다른 데이터 업데이트 
    ⇒ 한 트랜잭션 내에서 A가 한번 더 조회시 다른 값을 조회
    dirty-read 한 트랜잭션이 실행중일 때 다른 트랜잭션에 의해 수정되었지만 커밋되지 않은 행의 데이터를 읽을 수 있다.

    ex) A가 데이터를 업데이트 후 커밋하지 않은 상태
    ⇒ B가 조회시 업데이트된 내용이 조회됨

     

    🤖 MySQL 에서의 격리 수준


    1️⃣ SERIALIZABLE

    MySQL에서 SELECT FOR SHARE/UPDATE 는 대상 레코드에 각각 읽기 / 쓰기 잠금을 건다.

     

    반면, 일반적인 SELECT 문은 잠금없이 실행이 된다.

    그러나, SERIALIZABLE 격리 수준에서는 일반적인 SELECT 작업에서도 대상 레코드에 넥스트 키 락을 읽기 잠금(공유락, Shared Lock) 으로 건다.

    따라서, 한 트랜잭션에서 넥스트 키 락이 걸린 레코드를 다른 트랜잭션에서는 절대 추가/수정/삭제 할 수 없다.

     

    2️⃣ REPEATABLE READ

    🧩 일반적인 RDBMS

     

    일반적인 RDBMS는 변경 전의 레코드를 undo 공간에 백업을 해둔다.

    • 변경 전/후 데이터가 모두 존재해, 동일한 레코드에 여러 버전의 데이터가 존재한다
    • 이를 MVCC (Multi-Version Concurrency Control, 다중 버전 동시성 제어) 라고 한다.

     

    💡 MVCC를 통해 트랜잭션이 롤백된 경우 데이터를 복원할 수 잇고 서로 다른 트랜잭션간 접근할 수 있는 데이터를 제어할 수 있다.

    •  각각의 트랜잭션은 순차 증가하는 고유의 트랜잭션 번호가 존재해, 백업 레코드에서 이 트랜잭션 번호를 저장한다.

     

     

    ⚠️ REPEATABLE READ는 MVCC를 이용해 한 트랜잭션 내에서 동일한 결과를 보장하지만 새로운 레코드가 추가되는 경우에는 부정합이 생길 수 있다.

     

     

    👻 유령 읽기 (Phantom Read)

    • 트랜잭션이 끝나기 전에 다른 트랜잭션에 의해 추가된 레코드가 발견될 수 있다.
    • REPEATABLE READ는 새로운 레코드의 추가까지 막지 않아, 유령 읽기가 발생할 수 있다.

     

    하지만, MVCC 덕에 일반적인 조회에서는 유령 읽기가 발생하지 않는다.

    자신보다 나중에 실행된 트랜잭션에서 추가한 레코드는 무시하면 되기 때문

     

    https://mangkyu.tistory.com/299

     

     

    🤔 그럼 유령 읽기가 발생하는 상황은 언제일까?

    • 잠금이 사용되는 경우이다.

    https://mangkyu.tistory.com/299

     

     

    1️⃣ 사용자 B가 데이터를 조회하는데 SELECT FOR UPDATE를 통해 쓰기 잠금을 건다.

    • 베타적 잠금

     

    2️⃣ 사용자 A가 새로운 데이터를 INSERT 한다.

    • 이때, 일반적인 RDMBS에서는 갭 락이 존재하지 않아 id = 50인 레코드에만 락이 걸려 있다.

     

    3️⃣ 사용자가 B가 동일한 쓰기 잠금 쿼리로 다시 한번 데이터를 조회한다.

    • 이번엔 2건의 데이터가 조회된다.
    • Phantom Read

     

     MySQL에서는 갭 락이 존재해 위의 상황에서 Phantom Read가 발생하지 않는다.

     

    https://mangkyu.tistory.com/299

     

     

    1️⃣ 사용자 B가 SELECT FOR UPDATE로 데이터를 조회

    • MySQL은 id가 50인 레코드에 레코드락,
    • id가 50보다 큰 범위에는 갭 락으로 넥스트 키 락을 건다.

     

    2️⃣ 사용자 A가 id 가 51인 member를 INSERT 한다면, B의 트랜잭션이 종료될 때 까지 기다린다.

    • 대기를 오래하게 되면 락 타임아웃 발생

     

    따라서, 일반적으로 MySQL의 REPEATABLE READ에서는 Phantom Read가 발생하지 않는다.

     

    3️⃣ READ COMMITTED

    READ COMMITTED는 커밋된 데이터만 조회할 수 있다.

     

    Phantom Read에 더해 Non-Repeatable Read(반복 읽기 불가능) 문제까지 발생한다.

     

    https://mangkyu.tistory.com/299

     

     

    💣 READ COMMITTED가 문제가 발생하는 상황

    • 한 트랜잭션에서 입금된 총 합을 계산
    • 한 트랜잭션에서는 입금 내역을 계속해서 커밋

    이 상황에서는 같은 트랜잭션에서 입금된 내역이 조회할 때마다 달라져 문제가 발생할 수 있다.

     

    4️⃣ READ UNCOMMITTED

    커밋하지 않은 데이터 조차도 접근할 수 있는 격리 수준

     

    https://mangkyu.tistory.com/299

     

    하나의 트랜잭션의 작업이 완료되지 않았는데도, 다른 트랜잭션에서 변경된 데이터에 접근할 수 있다.

    • 부정합 문제 - Dirty Read가 발생

     

    💡 정리

    MySQL는 갭 락을 이용하기 때문에 Phantom Read가 거의 발생하지 않아 READ COMMITTED 보다는 동시 처리 성능이 뛰어난 REPEATABLE READ를 사용한다.

     

    📕 참고자료

    [MySQL] 트랜잭션의 격리 수준(Isolation Level)에 대해 쉽고 완벽하게 이해하기

    MySQL Gap Lock 다시보기

    트랜잭션 격리 수준

     

    '💻 computer science > 📦 database' 카테고리의 다른 글

    MySQL - 트랜잭션 격리 수준 실습  (0) 2024.05.11
    MySQL - 스토리지 엔진 수준의 락  (0) 2024.05.11
    인덱스  (0) 2022.10.05
    SQL / NoSQL  (1) 2022.10.05
    트랜잭션  (1) 2022.10.05

    댓글

Designed by Tistory.