ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 트랜잭션 격리수준
    DataBase 2022. 7. 21. 21:21

    트랜잭션

    트랜잭션 이란

    트랜잭션이란 여러 쿼리를 논리적으로 하나의 작업으로 묶어주는것을 이야기합니다.

    돈 거래로 트랜잭션의 예시를 들어보도록 하겠습니다. 거래가 일어날 때의 과정은 다음과 같습니다.

    1. 우선 구매자의 계좌에서 10,000원을 출금합니다.
    2. 다음 판매자에 계좌에 10,000을 입금합니다.

    이를 쿼리로 나타내면 이와 같이 나타낼 수 있습니다.

    UPDATE 문 : 구매자 계좌에 10,000 원 빼기

    UPDATE 문 : 판매자 계좌에 10,000 원 더하기

    마음처럼 되면 좋은데 출금 성공후 서버 다운이라든지 하는 이유로 오류가 생길 수 있습니다. 구매자의 계좌에서는 돈이 빠졌는데 판매자의 계좌에는 돈이 들어가지 않는 이런 상황을 방지하기 위해 나온것이 바로 트랜잭션입니다.

    즉, 트랜잭션은 하나의 작업으로 이루어지는 여러 쿼리 작업들을 트랜잭션이라는 논리적인 하나의 작업 단위로 묶어서 쿼리들이 한꺼번에 모두 실행되거나 아예 아무 쿼리도 실행되지 않게 해주는 것입니다. 트랜잭션은 사용자 혹은 시스템상의 실수가 있더라도 데이터베이스가 데이터를 안정적으로 보장할 수 있도록 합니다.

    하나의 트랜잭션은 커밋 혹은 롤백됩니다.

    커밋이란 일종의 확인 도장으로 트랜잭션으로 묶인 모든 쿼리가 성공되어 트랜잭션 쿼리 결과를 실제 디비에 반영하는 것이고 롤백은 쿼리 실행 결과를 취소하고 디비를 트랜잭션 이전 상태로 되돌리는 것입니다.

    트랜잭션의 성질

    이런 트랜잭션이 안전하게 수행된다는 것을 보장하기 위한 성질이 4가지 있습니다.

    앞글자들을 따서 주로 ACID 성질이라고 부릅니다.

    Atomic(원자성)

    • 트랜잭션은 DB에 모두 반영되거나, 전혀 반영되지 않아야 합니다.
      • 완료되지 않은 트랜잭션의 중간 상태를 DB에 반영해서는 안됩니다.
    • 중간 단계까지 실행되고 실패하는 일이 없도록 보장해줍니다.

    Consistency(일관성)

    • 트랜잭션 작업처리 결과는 항상 일관성이 있어야합니다. 즉, 데이터베이스는 항상 일관된 상태로 유지되어야 한다는 이야기입니다.
    • 디비에 여러 제약 조건에 맞는 상태를 보장해줍니다. 마이너스 통장을 허락하지 않는다는 DB의 조건이 있다면 이 조건이 위배될 때 트랜잭션은 바로 종료됩니다.

    Isolation(독립성)

    • 둘 이상의 트랜잭션이 동시 실행되고 있을때, 어떤 트랜잭션도 다른 트랜잭션 연산에 끼어들 수 없습니다.
    • 즉, 각각의 트랜잭션은 서로 간섭없이 독립적으로 이루어져야합니다.
    • 구매자의 계좌에서 돈이 빠져나가고 판매자의 계좌에 돈이 아직들어가지 않은 DB상황을 다른 트랜잭션이 조회하면 안됩니다.

    Durability(지속성)

    • 트랜잭션이 성공적으로 완료되었으면 결과는 영구히 반영되어야 합니다.
    • 한번 송금이 성공하면 은행 시스템이 문제가 생기더라도 송금이 성공한 상태로 복구 할 수 있어야 합니다.

    하지만 ACID 성질은 트랜잭션이 이론적으로 보장해야하는 성질이고 실제로는 성능을 위해 완화되기도 합니다.

    예를 들어 독립성을 완벽하게 보장하려고 하면 동일 데이터에 100개의 연결이 접근했을 시 이 100개 연결을 순차적으로 해결해야 합니다. 그 결과 동시성이 매우 떨어지는 문제가 발생하게 됩니다. 따라서 동시성을 얻기 위한 한가지 방법으로 트랜잭션의 격리레벨 설정이 있습니다 .

    트랜잭션 격리 수준

    동시에 DB에 접근할 때 그 접근을 어떻게 제어할지에 대한 설정입니다. 표준적으로 4가지의 레벨이 존재합니다.

    밑으로 갈수록 격리 수준이 높아지지만 성능이 떨어집니다. 데이터 정합성과 성능이 반비례하므로 케이스에 맞게 잘 선택하는 것이 중요합니다.

    READ-UNCOMMITTED

    첫번째 격리 레벨은 격리 수준이 가장 낮은 READ-UNCOMMITTED 입니다.

    해당 수준은 커밋 전의 트랜잭션의 데이터 변경 내용을 다른 트랜잭션이 읽는 것을 허용 합니다.

    그림을 보면 트랜잭션 A가 아직 커밋되지 않은 상태에서 트랜잭션 B가 DB를 조회했습니다. 커밋되지 않고 변경된 트랜잭션 A의 값을 조회하는것을 볼 수 있습니다.

    READ-UNCOMMITTED 레벨에서는 더티리드 라는 현상이 발생할 수 있습니다.

    더티리드란 어떤 트랜잭션에서 처리한 작업이 완료되지 않았는데도 다른 트랜잭션에서 볼 수 있는 현상(트랜잭션 A가 만약 트랜잭션을 끝마치지 못하고 롤백한다면 트랜잭션 B는 무효가 된 데이터 값을 읽는 것)을 얘기합니다.

    READ-UNCOMMITTED 는 가장 낮은 격리수준을 갖는 설정으로 Dirty-Read 뿐 아니라 Non-Repeatable Read, Phantom Read 와 같은 문제도 나타납니다.

    READ-COMMITTED

    두번째 격리 레벨인 READ-COMMITTED 입니다.

    Oracle DBMS 에서 기본으로 사용되는 격리 수준입니다.

    커밋이 완료된 트랜잭션의 변경사항만 다른 트랜잭션에서 조회 가능합니다. 트랜잭션이 이루어지는 동안 다른 트랜잭션은 해당 데이터에 접근이 불가능합니다.

    아직 커밋하지 않은 상태라면 트랜잭션 시작 전 값을 읽어오고 커밋하면 변경된 데이터를 읽어옵니다.

    READ-COMMITTED 레벨에서는 Non-Repeatalbe Read 와 Phantom read 현상이 발생합니다.

    Non-Repeatable Read 는 위의 예에서 보듯이 Transaction B 내에서 select 문을 두번 조회했는데 두 값이 다른 값이 나오는 데이터 불일치 문제입니다.

    REPEATABLE-READ

    세번째 격리레벨인 Repeatable Read 입니다.

    MySQL의 InnoDB 스토리지 엔진에서 기본으로 사용되는 격리수준입니다.

    마찬 가지로 커밋이 완료된 데이터만 읽을 수 있습니다.

    READ-COMMITED 와 다른점은 한 트랜잭션이 조회한 데이터는 트랜잭션이 종료될 때 까지 다른 트랜잭션이 변경하거나 삭제하는 것을 막으므로 한번 조회한 데이터는 반복적으로 조회 해도 같은 값을 반환합니다.

    이렇게 완벽해 보이는 격리 레벨에서도 문제가 발생합니다.

    바로 Phantom Read 입니다.

    Phantom Read 는 Non-Repeatable Read 의 한 종류로 조건이 걸렸든 안 걸렸든 select 문을 쓸 때 나타날 수 있는 현상입니다. 해당 쿼리로 읽히는 데이터에 들어가는 행이 새로 생기거나 없어져 있는 현상입니다.

    SERIALIZABLE

    마지막으로 격리 레벨이 가장 높은 것은 SERIALIZABLE 레벨입니다. 한 트랜잭션에서 사용하는 데이터를 다른 트랜잭션에서 접근 할 수 없습니다.

    트랜잭션의 ACID 성질이 엄격하게 지켜지나 성능은 가장 떨어집니다. 단순 SELECT 문으로도 트랜잭션이 커밋될 때까지 모든 데이터에 잠금이 설정되어 다른 트랜잭션에서 해당 데이터를 변경할 수 없게 됩니다.

    각 격리 레벨에서 발생할 수있는 문제점을 표로 정리한 것은 다음과 같습니다.

    Dirty ReadNon-Repeatable ReadPhantom Read

    READ_UNCOMMITTED O O O
    READ_COMMITTED X O O
    REPEATABLE_READ X X O
    SERIALIZABLE X X X

    참고

    https://www.youtube.com/watch?v=e9PC0sroCzc

    'DataBase' 카테고리의 다른 글

    샤딩과 파티셔닝  (0) 2022.03.19
    MySQL 대소문자 구별  (0) 2022.03.01
    MYSQL GROUP BY  (0) 2021.02.11

    댓글