본문으로 바로가기

DB 격리성

category Database 2018. 2. 10. 02:06
    반응형

    트랜잭션은 일련의 쿼리를 원자성있게 제공해준다. 


    원자성, 일관성, 영속성, 격리성


    그중 격리성에 대해서 알아보자


    낮은 격리성으로 발생가능한 현상



    1. DirtyRead

    : 만약 T1(Transaction 1)이 데이터를 수정했다. T2가 수정된 데이터를 읽어서 작업을 하는데, T1이 롤백이 되면 T2는 잘못된 데이터를 가져가는 것.


    2. Non-Repeatable Read

    : T1이 조회했고, T2가 업데이트 커밋, T1이 조회했을 경우 다른 값이 나온다.


    3. Phantom

    : T1이 조회했고, T2가 삽입/삭제, T1에 새로운 로우가 나타남.



    DB 락


    공유락 : 읽기만 가능

    배타락 : 모두 불가능


    격리성 수준

    1. Read Uncommitted


    : 커밋되지 않은 데이터를 읽을 수 있다. 즉 변경 가능성이 있는 데이터도 읽을 수 있는 것. 

    : 아무것도 막아주지 않는다.

    : DirtyRead, Non-Repeatable Read, Phantom  발생 가능성이 있다.



    2. Read Committed


    : 커밋된 데이터만을 읽을 수 있다.  

    : 업데이트, 삽입/삭제는 막아주지 않는다.

    : DirtyRead가 발생하지 않는다. 하지만 Non-Repeatable Read, Phantom이 발생한다.



    3. Repeatable Read


    : 두번 조회했을 때 결과값이 같은 것을 보장해준다.

    : 업데이트는 막아주지만, 삽입/삭제는 막아주지 않는다.

    : 하지만 삽입시 발생하는 Phantom은 보장해주지 않는다.


    : 트랜잭션이 끝날 때까지 락을 걸어. 수정이 불가능하게 한다.


    4. Serializable Read

    : 모두 보장



    다중버전동시성제어


    : 스냅샵을 찍어둔다.

    : 읽기와 쓰기를 분리.

    : 스냅샷을 읽는 트랜잭션은 추가, 삭제, 업데이트를 무시한다.



    개발과 연관해서 생각해보자.


    : 현재 우리 시스템도 Read Committed를 사용한다.

    : 데이터를 읽어오고 업데이트 시도 시 updDate가 변경되어 있으면 다시 읽어와 시도하는 DoTrasactionJob함수를 사용한다. 만약 3번이상 실패 시 트랜잭션 예외를 던진다.

    : WAS환경에서 하나의 API에 동시 호출이 발생하면, 둘다 진입이 가능하게 된다. 그러므로 Redis Lock을 걸어준다.

    : 최근 사건으로는 매칭로직에 두개 요청이 한번에 들어왔다. 매칭은 나와 제일 비슷한 팀을 매치를 해주는데. 전 경기에 해당되는 팀은 제거된다. 하지만 하나의 트랜잭션이 커밋이 되기전에 전경기를 조회하기 때문에 둘다 같은 팀이 매치되게 된다. 그래서 결국 셔플을 진행했다.


    : 결국엔 크리티컬한 문제가 발생하면 락을 걸어주는게 맞는거다.



    Mysql 트랜잭션 격리성 레벨 확인 쿼리

    : show variables like 'tx%'



    반응형