Spring

@Transactional에 대하여

Hoonco 2022. 8. 30. 18:14

 

트랜잭션이란?

DBMS에서 기능을 수행하기 위한 작업 혹은 상호작용의 단위이다.

즉 여러개의 쿼리를 하나로 묶는 단위이다

begin과 commit을 자동으로 수행해주기도 하며 예외 발생시 rollback 처리를 자동으로 수행한다.

 

먼저 트랜잭션에 대하여 간단하게 알아보자.

 

트랜잭션의 성질 (ACID) 

 

1. 원자성

  • 트랜잭션 내에서 실행한 작업들은 마치 하나의 작업인 것처럼 모두 성공하거나 모두 실패해야 한다.

2. 일관성

  • 모든 트랜잭션은 일관성 있는 데이터베이스 상태를 유지해야 한다.
  • 예를 들어 데이터베이스에서 정한 무결성 제약 조건을 항상 만족해야 한다.
  • 무결성: 데이터의 정확성, 일관성, 유효성을 유지하는 것
  • 무결성의 종류 
    • 개체 무결성: 기본키로 선택된 필드는 빈 값을 허용하지 않는다.
    • 참조 무결성: 서로 참조 관계에 있는 두 테이블의 데이터는 항상 일관된 값을 유지해야 한다.
    • 고유 무결성: 특정 속성에 대해 고유한 값을 가지도록 조건이 주어진 경우 그 속성 값은 모두 고유한 값을 가진다.
    • NULL 무결성: 특정 속성 값에 NULL이 올 수 없다는 조건이 주어진 경우 그 속성 값은 NULL이 될 수 없다

 

3. 격리성 (독립성)

  • 동시에 실행되는 트랜잭션들이 서로에게 영향을 미치지 않도록 격리한다.
  • 예를 들어 동시에 같은 데이터를 수정하지 못하도록 해야한다 ( DB Lock )
  • 격리성은 동시성과 관련된 성능 이슈로 인해 트랜잭션 격리 수준(Isolation level)을 선택 할 수 있다.

4. 지속성

  • 트랜잭션을 성공적으로 끝내면 그 결과가 항상 기록되어야 한다. 중간에 시스템이 문제가 발생해도 데이터베이스 로그 등을 사용해서 성공한 트랜잭션 내용을 복구해야 한다.

 

트랜잭션 격리 수준 (Isolation)

 

READ_UNCOMMITED               LEVEL 0

  • 가장 낮은 격리 수준
  • 트랜잭션이 커밋되기 이전에 다릍 트랜잭션에 노출되는 문제가 있지만 가장 빠름
  • 이는 데이터 무결성을 위해 되도록이면 사용하지 않아야 하나
    몇몇 행이 제대로 조회되지 않더라도 괜찮은 거대한 양의 데이터를 어림잡아 집계하는데 사용하면 좋다.
    이를 더티 리드라고도 한다

 

READ_COMMITED                    LEVEL 1

  • 가장 많이 사용 되는 격리 수준이며 My SQL, PostgresSQL 등 여러 DBMS에서 기본값으로 설정되어 있다.
  • 다른 트랜잭션이 커밋하지 않은 정보는 읽을 수 없다. 즉, 커밋 완료된 데이터에 대해서만 조회를 허용
  • 하지만 어떤 트랜잭션이 접근한 행을 다른 트랜잭션이 수정할 수 있다.
  • 예를 들어 트랜잭션 A가 수정한 행을 트랜잭션 B가 수정할 수도 있다.
  • 이 때문에 트랜잭션 A가 같은 행을 다시 읽을 때 다른 내용이 발견될 수 있다.
    이를 반복 가능하지 않은 조회라고 한다.

 

REPEATEBALE_READ              LEVEL 2

  • 하나의 트랜잭션이 수정한 행을 다른 트랜잭션이 수정할 수 없도록 막아주지만
    새로운 행을 추가하는 것은 막지 않는다.
  • 때문에 이후 추가된 행이 발견될 수도 있다 이를 팬텀리드라고 한다.

 

SERIALIZABLE                           LEVEL 3

  • 트랜잭션을 순차적으로 진행
  • 여러 트랜잭션이 동시에 같은 행에 접근할 수 없다.
  • 매우 엄격한 수준으로 해당 행에 대해 격리 시키고 이후 트랜잭션이 이 행에 대해 일어난다면 기다려야 한다.
  • 때문에 교착 상태가 일어날 확률도 많고 가장 성능이 떨어지는 격리 수준

 

단순히 조건으로 보면 레벨이 높을 수록 좋아 보이지만

각 격리 수준마다의 장잔점이 있다.

때문에 무슨 로직이냐에 따라서 고민하고 수준을 지정해야한다.

 

Spring Transaction

 

 @Transactional

Spring에서 사용되는 어노테이션으로.

메소드, 클래스, 인터페이스에 추가하여 사용 할 수 있다.

이를 선언적 트랜잭션이라고 하며

프록시 객체가 생성되어 자동으로 커밋과 롤백을 진행해준다.

 

Annotaion Option

  1. isoloation
    • DB 데이터허용 수준(격리 수준)을 설정한다.
    • 위에서와 같은 READ_UNCOMMITED, READ_COMMITED, REPEATEABLE_READ, SERIALIZABLE을 설정 할 수 있다.
    • Default 값은 사용 하는 DBMS의 기본 격리 수준을 따른다.
  2. propagation
    • 트랜잭션 동작 도중 다른 트랜잭션이 호출될 경우 어떻게 할지 지정하는 옵션이다.
    • 트랜잭션 전파 라고도 한다.
      • REQUIRED
        • 이미 진행중인 트랜잭션이 있으면 해당 트랜잭션의 속성을 따른다. 아니라면 새로운 트랜잭션을 생성한다.
      • REQUIRES_NEW
        • 항상 새로운 트랜잭션을 생성하낟. 이미 진행되고 있는 트랜잭션이 있다면 보류 후 해당 트랜잭션을 먼저 작업한다.
      • SUPPORT
        • 이미 진행중인 트랜잭션이 있으면 해당 트랜잭션의 속성을 따르고, 없다면 트랜잭션을 설정하지 않는다.
      • NOT_SUPPORT
        • 이미 진행중인 트랜잭션이 있다면 보류하고, 트랜잭션 없이 작업을 수행한다.
      • NEVER
        • 트랜잭션이 진행중이지 않을때 수행한다. 있다면 Exception을 발생 시킨다.
      • NESTED
        • 진행중인 트랜잭션이 있다면 중첩 트랜잭션이 실행되며, 존재하지 않으면 REQUIRED와 동일하다.
      • MANDATORY
        • 이미 진행중인 트랜잭션이 있어야만 작업이 수행된다. 없다면 Exception을 발생 시킨다.
      •  
  3. noRollbackFor
    • 특정 예외 집어 해당 예외에 한해서는 rollback 하지 않는다.
  4. rollbackFor
    • 특정 예외 발생 시 rollback 한다.
    • @Trasactional은 모든 예외에 대해 롤백을 수행하지 않는다. 
      (Unchecked Exception or Error 만을 rollback 한다)
    • 때문에 모든 예외에 대해 롤백을 처리하고 싶은 경우
      @Transactional(rollbackFor= Exception.class)로 지정해주어야 한다.
  5. timeout
    • 지정 시간내에 메소드의 수행이 완료되지 않으면 rollback 한다.
  6. readOnly
    • 트랜잭션을 읽기 전용으로 설정한다.
    • 읽기 전용으로 설정시 성능이 조금이나마 상승한다.
    • readyOnly가 true인 트랜잭션에서 insert, update, delete가 실행되면 예외가 발생한다.

 

 

옵션 설정법

해당 사진은 설정별 방법을 보여 준 것이지 이와 같이 구성하면 안된다.

 

 

스프링은 오랫동안 사용된 만큼 서버관리에 대한 노하우나, 꿀 기능들이 스프링 내부에 많이 녹아들어 있다.

허나 이러한 점을 모른다면 매우 고생할 뿐만 아니라.
어떠한 부분에서 문제가 되는지도 파악이 안될 경우가 있다.
이를 방지하기위하여 미리미리 공부를 해놓도록 하자.