ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Spring] 트랜잭션이란? 전파 (Transaction Propagation) 속성과 격리레벨(Isolation level)
    Spring 2022. 9. 1. 23:39

     

     

    트랜잭션 (Transaction)이란?

     

    Transaction is All or Nothing!

     

    트랜잭션을 한마디로 정의하자면 다음과 같습니다.

    SQL에서 DML문장 수행 후 COMMIT 과 ROLLBACK을 적용하는 것과 같은 개념입니다.

     

    예를들어, 상대방에게 계좌이체를 하는 상황을 가정합니다.

    내 통장에서 돈이 빠져나가고 -> 상대방의 계좌에 돈이 입금되는 것까지 완료되어야 계좌이체가 성공했다고 할 수 있습니다.

     

    만약 내 통장에서는 돈이 빠져나갔는데, 상대방의 계좌에는 입금이 안되었다면, 내 통장에서 돈이 빠져나가는 과정까지 모두 취소되어야 합니다.

     

    이렇게 일련의 과정들을 하나의 단위로 묶어서 모두 성공시 수행(COMMIT), 하나의 처리라도 오류가 발생한다면 원래 상태로 되돌리는 것(ROLLBACK)을 트랜잭션 처리라고 합니다.

     

    이렇게 트랜잭션 자체는 개념이고, Spring aop에서는 트랜잭션 코드와 일반 코드를 분리하기 위해 @Transactional 이라는 어노테이션 형태로 제공합니다.

     


     

    트랜잭션의 전파속성(Transaction Propagation)

     

    @Transactional 어노테이션에는 전파속성을 지정할 수 있습니다. (Propagation enum상수로 제공)

    이를 사용해 여러개의 트랜잭션을 처리할 때 어떻게 처리할 것인지를 지정할 수 있습니다.

     

     

    1. REQUIRED

    - Defualt 속성입니다. 트랜잭션의 시작지점, 근원과 같은 개념입니다.
    - 기존 트랜잭션이 없으면 새로운 트랜잭션을 만듭니다.
    - 기존 트랜잭션이 있으면 기존 트랜잭션에 포함됩니다.
    - 기존 트랜잭션에 포함되었을 때는 기존 트랜잭션의 커밋이 완료될 때 커밋되고, 롤백시 함께 취소됩니다.

     

     

    2. MANDATORY

    - 반드시 기존 트랜잭션 하에서만 수행이 가능합니다. 근데, 아무 트랜잭션이 아닌 특정 트랜잭션 하에서만 수행됩니다.
    - 기존 트랜잭션이 없으면  IllegalTransactionStateException 예외를 발생합니다.

     

     

    3. NESTED

    - 기존 트랜잭션이 없으면 새로운 트랜잭션을 만듭니다.
    - 기존 트랜잭션이 있으면 중첩 트랜잭션을 만듭니다.
    - 커밋 시점은 부모 트랜잭션(기존 트랜잭션)이 완료될 때이지만, 롤백 시엔 부모 트랜잭션에 영향을 주지 않습니다.
    - 만약 부모 트랜잭션에서 롤백이 발생한다면 이 트랜잭션도 롤백됩니다.

     

     

    4. NEVER

    - 어떤 경우에서도 트랜잭션을 생성하지 않습니다.
    - 만약 트랜잭션 하에 수행된다면 llegalTransactionStateException 예외를 발생합니다.

     

     

    5. NOT_SUPPORTED

    - 기존 트랜잭션이 없어도 새로운 트랜잭션을 생성하지 않습니다.
    - 만약 기존 트랜잭션이 존재한다면 기존 트랜잭션을 보류하고, 트랜잭션 없이 진행합니다.

     

     

    6. REQUIRES_NEW

    - 트랜잭션의 존재여부와 상관없이 무조건 자신만의 새로운 트랜잭션을 생성합니다.
    - 기존 트랜잭션이 존재한다면 기존 트랜잭션을 보류하고 새로운 트랜잭션을 생성합니다.
    - 롤백시 서로의 TX에 영향을 주지 않습니다.

     

     

    7. SUPPORTS

    - 기존 트랜잭션이 없으면 그대로 트랜잭션 없이 진행합니다.
    - 기존 트랜잭션이 있으면 그 트랜잭션에 포함됩니다.

     

     

    각 속성이 비슷한 듯 하면서 미세하게 달라서 헷갈려서, 각각의 차이점과 특징을 정리해보았습니다.

     

     


     

    트랜잭션 격리레벨(Transaction Isolation Level)

     

    여러개의 트랜잭션이 동시에 수행될 때, 다른 트랜잭션에게 결과를 어떻게 보여줄 것인지에 대한 설정입니다.

    원래 트랜잭션의 대전제 중에는 각 트랜잭션끼리는 격리되어야 한다.(Isolation 성질을 갖는다)가 있습니다.

     

    그러나 이 대전제를 격리수준을 조절함으로써 깨뜨릴 수 있습니다.

     

    스프링에서는 이 또한 @Transactional의 속성으로 지정할 수 있게끔 enum 상수로 제공합니다.

     

    1. DEFAULT

    - 사용중인 데이터소스에 설정된 격리수준을 그대로 따릅니다. 따로 지정하지 않아도 되는 기본 설정입니다.
    - 대부분의 데이터베이스는 READ_COMMITED을 기본으로 사용합니다.

     

     

    2. READ_COMMITED

    - COMMIT이 완료된 데이터만 SELECT할 수 있도록 제공합니다.

     

     

    3. READ_UNCOMMITED

    - READ_COMMITED의 반대입니다. 아직 커밋이 완료되지 않은 데이터도 읽을 수 있습니다.
    - 성능이 가장 빠르지만, 그만큼 불안성도 높습니다.

     

     

    4. REPEATABLE_READ

    - 테이블의 같은 행에 대해 두 가지 이상의 다른 행위를 하는 트랜잭션들이 있을 때,
    - 한번 읽은 행은 반복적으로 읽어온다 하더라도 다른 트랜잭션의 변경 결과를 읽어오지 않습니다.

    - 그러나 새로운 행을 추가하는 것에 대해서는 따로 제한을 두지 않아서, 전체 행을 조회할 경우 새롭게 추가된 행이 나타날 수 있습니다.

     

     

    5. SERIALIZABLE

    - 가장 강력한 격리수준입니다.
    - 각 트랜잭션을 먼저 도착한 순서대로 수행하고, 이전 트랜잭션이 완료된 후에야 다음 트랜잭션을 수행합니다. 즉, 동시에 여러 트랜잭션이 하나의 테이블에 접근할 수 없습니다.

    - 가장 안전하지만, 성능면에서는 가장 떨어지기 때문에 정말 안전해야하는 상황이 아니라면 적용하지 않습니다.

     

    댓글

Designed by Tistory.