[ Spring ] @Transactional 잘 사용하자

신범철·2023년 5월 28일
0

스프링부트

목록 보기
8/20

서론

스프링 프로젝트를 하면서 @Transactional이라는 애노테이션을 자주 사용한다.
하지만 정확하게 어떻게 사용하는지 모르기에 정리를 시작한다..😶😶

Transaction ACID

Transaction은 데이터베이스의 상태를 변화시키기 위해 수행하는 작업의 단위이다.

ACID(원자성, 일관성, 고립성, 지속성)는 데이터베이스 트랜잭션이 안전하게 수행하는 것을 보장하기 위한 성질이다.

  • 원자성(Atomicity)
    • 한 트랜잭션 내에서 실행하는 작업들은 모두 성공하거나 모두 실패해야한다.
  • 일관성(Consistency)
    • 트랜잭션이 실행을 성공했을 때 이전의 상태와 결과의 상태가 항상 일관된 상태로 있어야한다.
  • 격리성(Isolation)
    • 동시에 실행되는 트랜잭션들이 서로 영향을 미치지 않도록 격리
  • 영속성(Durability)
    • 성공적으로 수행된 트랜잭션은 영원히 반영되어야 한다는 성질

일반적인 @Transactional

public class UserService {

        @Transactional 
        public Long registerUser(User user) {
                // execute some SQL that e.g. 
                // inserts the user into the db and retrieves the autogenerated id 
                // userDao.save(user); 
                return id;
        } 
}
  • 일반적으로 Service Layer에서 사용된다.
  • @Transactional 어노테이션을 사용하려면 설정에서 @EnableTransactionManagement을 추가해야하는데 스프링부트는 자동으로 추가해준다.
  • @Transactional 어노테이션을 포함한 메서드가 호출되면 설정이 저장된 @EnableTransactionManagement에서 트랜잭션을 시작한다. 메서드가 실행하기 전에 begin을 호출하고, 메서드가 종료된 뒤 commit을 호출한다. 비정상일 경우, Rollback을 한다.

@Transactional 추가정보

@Transactional을 사용하기 위해서는 Spring AOP의 동작과정, 프록시 생성, 주의사항(rivate/protected 메서드는 @Transaction을 무시한다.)을 알아야 하는데 이는 링크에 너무 잘 정리되어 있어 읽어보고 넘어가자

@Transactional Options

  • isolaion

    • 트랜잭션에서 일관성 없는 데이터를 허용하는 수준 설정(격리 수준)
  • propagation

    • 동작 도중 다른 트랜잭션을 호출할 때, 어떻게 할 것인지 지정하는 옵션(전파 옵션)
  • noRollbackFor

    • 특정 예외 발생 시 rollback이 동작하지 않도록 설정
  • rollbackFor

    • 특정 예외 발생 시 rollback이 발생하도록 설정
  • timeout

    • 지정한 시간 내에 메소드 수행이 완료되지 않으면 rollback이 동작하도록 설정
  • readOnly

    • 트랜잭션을 읽기 전용으로 설정

isolation

트랜잭션 문제상황

  • Dirty read: 동시 트랜잭션의 커밋되지 않은 변경 내용을 조회하는 상황 (데이터 불일치)
  • Nonrepeatable read: 동시 트랜잭션이 동일한 행을 업데이트하고 커밋하는 경우, 행을 다시 조회할 때 다른 값을 얻 는 상황
  • Phantom read: 다른 트랜잭션이 특정 범위의 행을 추가/제거할 경우, 커밋 전/후 조회 결과가 다른 상황
@Transactional(isolation = Isolation.READ_UNCOMMITTED)
public void example(String message) {
    // ...
}

격리 레벨 설정

  • DEFAULT
  • READ_UNCOMMITTED (level 0)
  • READ_COMMITTED (level 1)
  • REPEATABLE_READ (level 2)
  • SERIALIZABLE (level 3)

propagation

트랜잭션 동작 도중 다른 트랜잭션을 호출하는 상황에서 선택할 수 있는 옵션

@Transactional(propagation = Propagation.REQUIRED)
public void example(String user) { 
    // ... 
}

전파 전략 설정

  • REQUIRED (default)
  • SUPPORTS
  • MANDATORY
  • NEVER
  • NOT_SUPPORTED
  • REQUIRES_NEW
  • NESTED

rollbackFor, noRollbackFor

선언적 트랜잭션에서 런타임 예외가 발생하면 롤백 수행
특정 상황에서 강제로 롤백하거나 런타임 예외에서 롤백 제외

@Transactional(rollbackFor=Exception.class)
@Transactional(noRollbackFor=Exception.class)

timeout

지정한 시간 내에 해당 메서드 수행이 완료되지 않은 경우 rollback(단위 : second)

@Transactional(timeout=10)

readOnly

  • 트랜잭션을 읽기 전용으로 설정
  • 성능을 최적화하기 위해 사용하거나, 특정 트랜잭션 작업안에서 변경을 일어나는 것을 의도적으로 방지하기 위해서 사용
  • readOnly = true인 경우 INSERT, UPDATE, DELETE 작업 진행 시 실행 시 예외 발생(default : false)
@Transactional(readOnly = true)

참고 문헌

AOP 동작원리

@Transactional Option

@Transactional Option2

Transactions with Spring and JPA

profile
https://github.com/beombu

0개의 댓글