Transactional 심화 / Isolation (격리 수준)
Propagation (전파 전략)
1. PROPAGATION_REQUIRED ( JpaTransactionManager Default )
- 부모 트랜잭션이 존재할 경우
- 부모 트랜잭션에 참여한다.
- 부모 트랜잭션이 없을 경우
- 새 트랜잭션을 시작한다.
일반적으로 사용되는 트랜잭션의 전파유형이다.
즉, 어떻게 해서든 (상속받서든, 내가 새로만들든) Transaction 을 시작하는 전파 유형
작한다.
2. PROPAGATION_SUPPORTS
- 부모 트랜잭션이 존재할 경우
- 부모 트랜잭션에 참여한다.
- 부모 트랜잭션이 없을 경우
- non-transactional 하게 동작한다.
부모 따라서 전파되는 유형
3. PROPAGATION_MANDATORY
- 부모 트랜잭션이 존재할 경우
- 부모 트랜잭션에 참여한다.
- 부모 트랜잭션이 없을 경우
- Exception이 발생한다.
트랜잭션에 참여하도록 강제하는 유형
4. PROPAGATION_REQUIRES_NEW
- 부모 트랜잭션 유무에 상관없이
- 새 트랜잭션을 시작한다.
- 부모 트랜잭션이 존재할 경우
- 부모 트랜잭션을 중지 시킨다.
무조건 새 트랜잭션을 생성하도록 강제하는 유형
5. PROPAGATION_NOT_SUPPORTED
- 부모 트랜잭션 유무에 상관없이
- non-transactional 하게 동작한다.
- 부모 트랜잭션이 존재할 경우
- 부모 트랜잭션을 중지 시킨다.
6. PROPAGATION_NEVER
- 부모 트랜잭션이 존재할 경우 Exception이 발생한다.
항상 non-transactional 하게 동작하는 유형
@RunWith(SpringRunner.class)
@SpringBootTest
public class TransTest {
@Autowired
Parent parent;
@Test
@Transactional(propagation = Propagation.NOT_SUPPORTED) // 트랜잭션 생성 방지
public void transactionalPropagationTest() {
parent.parentMethod(); // 부모 메서드 실행
}
}
@Component
public class Parent {
@Autowired
Child child;
@Transactional
public void parentMethod() {
System.out.println("Parent");
child.calledMethod();
}
}
@Component
public class Child {
@Transactional(propagation = ?) // <- 여기에 하나씩 넣어보세요.
public void calledMethod() {
System.out.println("Child");
}
}
Isolation (격리 수준)
조회시점에 다른 트랜잭션들과 얼만큼 격리하여 얼마나 정확한 데이터 목록을 얻을지 결정한다.
고립도와 성능의 Trade-off 를 조절
READ UNCOMMITTED
다른 트랜잭션에서 커밋되지 않은 내용도 참조할 수 있다
READ COMMITTED - 현업 사용
다른 트랜잭션에서 커밋되 내용만 참조할 수 있다.
REPETABLE READ - 현업 사용
트랜잭션에 진입하기 이전에 커밋된 내용만 참조할 수 있다.
SERIALIZABLE
트랜잭션에 진입하면 락을 걸어 다른 트랜잭션이 접근하지 못하게 한다. (성능이 매우 떨어짐)
rollbackFor
@Transactional 은 기본적으로 Unchecked Exception, Error 만을 rollback 해줍니다.
그렇기 때문에 모든 예외에 대해서 rollback을 진행하고 싶을 경우(rollbackFor = Exception.class) 를 붙여야 합니다.
🤔 Exception 구분
Checked Exception : 예상된 에러로 해당 쓰레드내에서 회복이 가능한 예외
Unchecked Exception, Error : 예상치 못한 에러로 회복이 불가능한 예외
✋ 따라서, 근본적으로 HTTP API는 잘못된 요청에서 회복할 수 없다
클라이언트는 백엔드 API의 예외로부터 회복할 수 없다. 예외 발생 시 request의 라이프 사이클은 400, 404, 500 등 응답을 반환하고 끝이 난다. 클라이언트가 이 request를 회복 시킬 수는 없다. 다만 새로운 요청을 보낼 뿐이다. 클라이언트는 아무것도 할 수 없고 백엔드는 회복할 수 없다. 현재 프로그램의 흐름 내에서 회복할 수 있을때만 checked exception을 사용해야한다.