[Spring] 트랜잭션 전파
하나의 트랜잭션 안에서 또 다른 트랜잭션을 호출할 시,
기존 트랜잭션에 병합할지 하이면 새로운 트랜잭션으로 분류하여 독립적으로 실행할지
결정하는 정책이다.
전파에 대한 옵션 (Propagation)
| REQUIRED (기본값) | 기존 트랜잭션 있으면 참여, 없으면 새로 생성 |
| REQUIRES_NEW | 무조건 새 트랜잭션 생성, 기존 트랜잭션은 잠시 중단 |
| NESTED | 기존 트랜잭션 내에 논리적 중첩 트랜잭션 생성 (savepoint 사용) |
| SUPPORTS | 트랜잭션이 있으면 참여, 없으면 그냥 실행 (비트랜잭션 가능) |
| NOT_SUPPORTED | 트랜잭션을 무시하고 비트랜잭션으로 실행 (읽기 전용에서 주로 사용) |
| MANDATORY | 반드시 트랜잭션 있어야 함, 없으면 예외 발생 |
| NEVER | 트랜잭션 있으면 예외 발생 |
timeout
트랜잭션 수행시간에 대한 타임아웃을 설정한다.
지정한 시간내에 완료되지 않으면 롤백을 수행한다.
기본값은 -1 (타임아웃 없음)이다.
@Transaction(timeout = 10)
rollbackFor
예외 발생시 체크예외도 옵션을 주어서 롤백을 해줄수 있다.
@Transactional(rollbackFor = Exception.class)
반대로 예외가 발생해도 롤백을 안하고 싶을땐
@Transactional(noRollbackFor=RuntimeException.class)
참고할 만한 블로그글 :
[Spring] @Transactional 옵션 알아보기 + 트랜잭션 전파
@Transactional에 대해 궁금하다면 아래 포스팅을 읽어보는 것을 추천드립니다. 트랜잭션이란? 특징과 사용법에 대해 쉽게 알아보자트랜잭션(Transaction) 트랜잭션은 DB의 상태를 변경시키기 위해 수
hstory0208.tistory.com
트랜잭션 격리 수준
여러 트랜잭션이 동시에 데이터에 접근할 때 데이터의 정합성과 일관성을 어떻게 보장할 것인지를 정의하는 동시성 제어 정책
“다른 트랜잭션이 내 데이터 읽거나 수정하는 걸 어디까지 허용할까?” 에 대한 설정
동시에 여러 트랜잭션이 실행될 때 다음과 같은 문제가 생길 수 있습니다:
| 문제 | 설명 |
| Dirty Read | 아직 커밋되지 않은 다른 트랜잭션의 데이터를 읽음 |
| Non-repeatable Read | 같은 쿼리를 두 번 실행했을 때 결과가 다름 |
| Phantom Read | 조건에 맞는 행이 트랜잭션 중간에 추가/삭제되어 결과가 바뀜 |
격리 수준 4단계
| 격리수준 | Dirty Read | Non-repeatable Read | Phantom Read |
| READ UNCOMMITTED | O | O | O |
| READ COMMITTED (기본: Oracle) | ❌ | O | O |
| REPEATABLE READ (기본: MySQL InnoDB) | ❌ | ❌ | O |
| SERIALIZABLE | ❌ | ❌ | ❌ |
1. READ_UNCOMMITTED
가장 낮은 격리수준으로 하나의 트랜잭션이 커밋되거 전에 그 변화가 다른 트랜잭션에 영향을 줄 수 있다,.
성능은 빠름, 하지만 Dirty Read 발생 가능 (매우 위험)
2. READ_COMMITED
다른 트랜잭션이 커밋하지 않은 정보를 읽을 수 없다.
대신 다른 트랜잭션이 읽은 로우를 또 다른 트랜잭션이 수정할 수 있어서
같은 쿼리를 두 번 해도 결과가 바뀔 수 있음 (Non-repeatable Read)
3. REPEATABLE_READ
트랜잭션 동안 같은 쿼리 결과는 동일함
한 트랜잭션이 읽는 튜플을 다른 트랜잭션이 수정할 수 없지만 새로운 튜플(행)에 대한 추가는 막을 수 없다.
4. SERIALIZABLE
트랜잭션을 순차적으로 실행하게 된다.
모든 읽기/쓰기/삽입을 차단하여 가장 강력한 정합성 보장 , 성능은 가장 느리다.
이러한 옵션은 아래와 같이 설정할 수있다.
@Transactional(isolation = Isolation.READ_COMMITTED)
public void someMethod(){
//작업 수행
}