스프링 부트에서는 @Transactional 어노테이션을 이용하여 복잡한 트랜잭션 처리를 단순화한다.
클래스, 메서드 단위로 어노테이션을 추가할 수 있고,
스프링이 AOP를 통해 프락시를 도입하여 트랜잭션 처리를 모두 해결해 준다.
@Transactional 세부 설정
트랜잭션의 세부 설정을 통해 상황별로 적절한 설정을 하여 성능을 최적화할 수 있다.
@Transactional 세부 설정 종류
- Isolation (격리 수준 설정)
- Propagation(전파 수준 설정)
- readOnly 속성
- 트랜잭션 롤백 예외 설정
- time-out 설정
1. Isolation(격리 수준)
일관성이 깨지는 것을 어느 정도까지 허용하느냐에 대한 설정이다.
기본 설정은 DEFAULT이다.
@Transactional(isolation=Isolation.DEFAULT)
@Transactional(isolation=Isolation.READ_COMMITTED)
READ_UNCOMMITTED (level 0)
트랜잭션 처리 중 또는 아직 커밋되지 않은 데이터를 다른 트랜잭션이 읽는 것을 허용한다.
사실상 격리를 하지 않는 정도.
- Dirty Read 발생
READ_COMMITTED (level 1)
트랜잭션 처리 중 다른 트랜잭션에서 접근할 수 없도록 막는다.
- Dirty Read 방지
- 트랜잭션이 종료되기 전까지 다른 트랜잭션에서는 해당 데이터에 접근할 수 없게 된다.
REPEATABLE_READ (level 2)
트랜잭션 처리 중 SELECT 문에서 사용하는 모든 데이터에 shared lock이 걸린다.
- Non-Repeatable Read 방지
- Phantom Read는 발생할 수 있다.
SERIALIZABLE (level 3)
가장 엄격한 격리 수준을 적용하여 완벽한 일관성을 제공한다.
- Phantom Read 방지
- 성능이 가장 낮아진다.
- 모든 격리 수준 관련 문제를 해결할 수 있다.
- 성능 문제로 거의 사용하지 않는다.
📁[Spring] 트랜잭션의 격리성 문제 - Dirty Read / Non-Repeatable Read / Phantom Read
2. Propagation (전파 수준)
@Transactional(propagation=Propagation.NESTED)
REQUIRED (기본 값)
항상 트랜잭션이 실행된다.
기존 부모 트랜잭션이 있으면, 해당 트랜잭션을 사용하고,
없으면 새로운 트랜잭션을 생성하여 사용한다.
REQUIRES_NEW
항상 새로운 트랜잭션에서 실행된다.
기존 트랜잭션이 있으면 일시중단 시킨다.
SUPPORTS
기존 부모 트랜잭션이 있으면 해당 트랜잭션을 사용하여 실행하고, 없으면 트랜잭션을 사용하지 않는다.
NESTED
항상 트랜잭션이 실행된다.
기존 트랜잭션이 있으면, 해당 트랜잭션에 Save point를 만들고 기존 트랜잭션 내에 중첩 트랜잭션을 만든다.
만약 오류 발생 시 Save point로 rollback 한다.
따라서 하위 트랜잭션은 상위 트랜잭션의 영향을 받지만,
더 중요한 상위 트랜잭션은 하위 트랜잭션에 영향을 덜 받게 된다.
3. readOnly
트랜잭션을 읽기 전용 속성으로 지정한다.
@Transactional(readOnly=true)
해당 트랜잭션에서는 조회만 가능하고, 수정은 불가하게 된다.
기능을 제한하는 설정이기 때문에, readOnly=true로 설정될 경우 성능이 향상된다.
4. 트랜잭션 롤백 예외 설정
예외 발생 시 트랜잭션을 롤백시키거나, 롤백시키지 않기 위한 옵션을 설정한다.
@Transactional(rollbackFor=MyException.class)
-> Exception 발생 시 롤백한다.
@Transactional(noRollbackFor=MyException.class)
-> MyException 발생 시에는 롤백하지 않는다.
default는 RuntimeException, Error이다.
5. Timeout
일정 시간 내에 트랜잭션이 종료되지 않으면 롤백한다.
@Transactional(timeout=10)
보통 하나의 트랜잭션의 시간이 많이 걸리지 않기 때문에,
timeout를 설정해 두면 오류 발생 시 너무 많은 시간을 잡아먹는 것을 방지할 수 있다.
트랜잭션 관련 글
📁[Database] 트랜잭션의 동작 원리와 ACID 속성
📁[Database] 트랜잭션 - 락(Lock) 동작 원리와 동작 과정
📁[Java, Spring] 트랜잭션을 적용하는 여러 가지 방법
📁[Spring] @Transactional 세부 설정 - 격리 수준 / 전파 수준 설정
📁[Database] 트랜잭션의 격리성 문제 - Dirty Read / Non-Repeatable Read / Phantom Read
(참고) 인프런 - 김영한 님 스프링 DB 1편
https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-db-1#
'JAVA & Spring > Spring' 카테고리의 다른 글
[Spring] 빈 스코프 (Bean Scope) / 싱글톤, 프로토타입 등 (0) | 2024.02.27 |
---|---|
[Spring] 빈 생명 주기 콜백 (Bean LifeCycle) @PostConstruct / @PreDestroy (0) | 2024.02.23 |
[Spring] 의존성 주입 방법 (DI : Dependency Injection), 생성자 주입 / 필드 주입 / setter 주입, 생성자 주입을 사용하는 이유 (0) | 2024.02.22 |
[Spring Boot] @RequestMapping 매핑 (0) | 2023.10.02 |
[Spring] application.properties와 application.yml의차이 (0) | 2023.08.18 |