spring

Spring Boot @Transactional

기기디 2022. 5. 24. 00:25

정의

  • 스프링에서 어노테이션으로 선언적 트랜잭션 방식으로 트랜잭션을 처리하는것을 말한다.

사용

  • 클래스, 인터페이스, 메소드에 사용할 수 있으면 메소드에 가장 가까운 어노테이션이 우선순위를 가진다.
  • 어노테이션이 적용된 범위에서 트랜잭션 기능이 포함된 프록시 객체가 생성되어 자동으로 commit, rollback을 진행해준다. 이 프록시 객체는 @Transactional이 포함된 메소드가 호출 될 경우 PlatformTransactionManager를 사용하여 트랜잭션을 시작하고 commit, rollback을 진행해준다.

주의해야할점 - 적용범위

  • 문제
    • 상위메소드에서 하위메소드를 호출하는 경우, 하위메소드에서만 @Transactional을 선언하여 상위메소드에서 하위메소드시 호출시 @Transactional이 적용되지 않는다.
  • 원인
    • @Transactional

옵션

isolation - 격리레벨

  • 역할
    • 트랜잭션에서 일관성 없는 데이터 허용 수준을 결정한다
  • 사용 - 격리레벨
    • DEFAULT
      • 기본격리수준으로 DB의 격리레벨을 따른다
    • READ_UNCOMMITED
      • 커밋되지 않는 데이터에 대한 읽기를 허용해준다. 다른 사용자가 특정 데이터에 대해서 수정을 하는동안 아직 커밋되지 않은 데이터를 읽을 수 있게된다.
      • DirtyRead가 발생한다. DirtyRead는 수정중인 데이터를 읽을 수 있으므로 롤백이 일어난 경우 잘못된 데이터를 읽게 되는 현상을 말한다.
    • READ_COMMITED
      • 커밋된 데이터에 대해 읽기를 허용한다. 하지만 다른 사용자가 특정 데이터에 대해 수정을 하는동안 다른 사용자는 해당 데이터를 읽을 수 없다.
      • DirtyRead를 방지한다.
    • REPEATEABLE_READ
      • 특정 데이터에 대해 다수의 사용자가 접근시 모두 다 동일한 결과를 보장한다. 사용자가 특정 데이터에 대해서 읽기를 진행하는 동안 shared lock이 걸리므로 다른 사용자는 해당 데이터에 대해서 수정이 불가능하다.
      • Non-Repeatable Read를 방지한다. Non-Repeatable Read는 트랜잭션a에서 데이터 a를 조회중에 트랜잭션b에서 데이터를 수정하고 커밋한다면 트랜젹선 a가 데이터a를 다시 조회했을때는 수정된 데이터가 조회되는 현상을 말한다.
    • SERIALIZABLE
      • 한 트랜잭션이 완료될때까지 SELECT구문이 사용하는 모든 데이터에 shared lock이 걸리므로 다른 트랜잭션은 lock이 걸린 데이터에 수정 및 입력이 불가능하다.
      • 데이터 일관성,동시성을 위하여 MVCC를 사용하지 않는다.
        • MVCC : 다수의 사용자가 데이터를 조회할때 성능을 위한 기술로 락을 사용하지 않고 데이터의 버전을 관리해서 일관성, 동시성을 높이는 기술을 말한다.
      • Phantom Read를 방지한다. Phantom Read는 트랜잭션a가 데이터집합을 반복조회했을 경우 트랜잭션b가 데이터를 추가하여 데이터집합의 갯수가 달라지는 현상을 말한다.

propagation - 전파레벨

  • 역할
    • 트랜잭션 동작 도중 다른 트랜잭션을 호출할 때, 어떻게 할 것인지 지정하는 옵션이다
  • 사용 - 전파속성
    • REQUIRED(DEFAULT)
      • 이미 진행중인 트랜잭션이 있다면 해당 트랜잭션 속성을 따르고, 진행중이 아니라면 새로운 트랜잭션을 생성한다.
    • REQUIRED_NEW
      • 항생 새로운 트랜잭션을 생성한다. 이미 진행중인 트랜잭션이 있다면 잠깐 보류하고 해당 트랜잭션 작업을 먼저 진행한다
    • SUPPORT
      • 이미 진행 중인 트랜잭션이 있다면 해당 트랜잭션 속성을 따르고, 없다면 트랜잭션을 설정하지 않는다.
    • NOT_SUPPORT
      • 이미 진행중인 트랜잭션이 있다면 보류하고, 트랜잭션 없이 작업을 수행한다.
    • MANDATORY
      • 이미 진행중인 트랜잭션이 있어야만, 작업을 수행한다. 없다면 Exception을 발생시킨다.
    • NEVER
      • 트랜잭션이 진행중이지 않을 때 작업을 수행한다. 트랜잭션이 있다면 Exception을 발생시킨다.
    • NESTED
      • 진행중인 트랜잭션이 있다면 중첩된 트랜잭션이 실행되며, 존재하지 않으면 REQUIRED와 동일하게 실행된다.

noRollbackFor - 예외무시

  • 역할
    • 특정 예외 발생 시 rollback하지 않는다

rollbackFor - 예외추가

  • 역할
    • 특정 예외 발생시 강제로 rollback시키도록 추가한다.

timeout

  • 역할
    • 지정한 시간 내에 메소드 수행이 완료되지 않으면 rollback한다

readOnly

  • 역할
    • @Transactional을 사용할때 트랜잭션을 읽기전용 모드로 설정할 수 있다.
    • 쓰기작업이 발생하는걸 의도적으로 막을 수 있다. Create / Update / Delete가 발생하면 에러를 던져준다.
  • 장점
    • JPA를 사용하는경우 성능향상의 이점이 있다. readOnly=true를 설정할 경우 FlushMode를 Manual로 변경하여 dirty checking(변경감지)를 생략한다. flush와 commit이 일어나지 않아 영속성 컨텍스트에서 스냅샷을 보관하지 않고 엔티티의 등록,수정,삭제가 일어나지 않는다. 이는 성능향으로 이어진다. 하지만 크게 성능향상이 이루어지지는 않는다고 한다.
    • 해당 메소드에서는 변경이 일어나지 않고 조회만 해야한다는걸 명확하게 명시해주기 위해서 사용한다.

테스트환경에서 @Transactional 사용시 주의해야할점

  • 테스트 메소드에 @Transactional을 적용시키면 메소드가 종료될때 자동으로 롤백된다.
  • TestTransaction클래스에 의해서 테스트환경에서는 무조건 롤백이 된다. 기본 옵션으로 롤백이 적용되어있고 변경이 가능하다.