1. Isolation
isolation은 데이터베이스의 트랜잭션 격리 수준을 설정하는 데 사용됩니다. 스프링에서 제공하는 Isolation 값은 java.sql.Connection의 TRANSACTION_* 상수와 매핑됩니다.
격리 수준 종류
Isolation Level | 설명 | 문제 방지 여부 |
Isolation.DEFAULT | 데이터베이스의 기본 격리 수준을 따릅니다. (보통 READ_COMMITTED) | 데이터베이스 기본 설정에 따름 |
Isolation.READ_UNCOMMITTED | 가장 낮은 격리 수준으로, 다른 트랜잭션의 커밋되지 않은 변경 사항을 읽을 수 있습니다. | Dirty Read 허용 |
Isolation.READ_COMMITTED | 커밋된 데이터만 읽을 수 있습니다. 다른 트랜잭션의 변경 사항이 커밋되기 전까지는 볼 수 없습니다. | Dirty Read 방지 |
Isolation.REPEATABLE_READ | 동일 트랜잭션에서 동일한 쿼리를 실행하면 항상 같은 결과를 보장합니다. | Dirty Read, Non-repeatable Read 방지 |
Isolation.SERIALIZABLE | 가장 높은 격리 수준으로, 트랜잭션 간 순차적으로 실행되도록 보장합니다. | Dirty Read, Non-repeatable Read, Phantom Read 방지 |
격리 수준별로 방지되는 문제
1. Dirty Read
- 한 트랜잭션에서 커밋되지 않은 데이터를 다른 트랜잭션이 읽는 상황.
- READ_COMMITTED 이상에서 방지됩니다.
2. Non-repeatable Read
- 동일한 쿼리를 두 번 실행했을 때, 다른 트랜잭션의 업데이트로 인해 다른 결과를 읽는 상황.
- REPEATABLE_READ 이상에서 방지됩니다.
3. Phantom Read
- 동일한 쿼리를 두 번 실행했을 때, 다른 트랜잭션의 INSERT/DELETE로 인해 결과 행의 수가 달라지는 상황.
- SERIALIZABLE에서 방지됩니다.
@Transactional(isolation = Isolation.REPEATABLE_READ)
public void someTransactionalMethod() {
// 트랜잭션 처리 로직
}
2. @Transactional의 다른 속성
1) propagation
트랜잭션 전파 행동을 정의합니다. 트랜잭션을 새로 시작하거나 기존 트랜잭션에 참여할지 결정합니다.
Propagation Type | 설명 |
REQUIRED | 기본값. 현재 트랜잭션이 존재하면 참여하고, 없으면 새 트랜잭션을 생성합니다. |
REQUIRES_NEW | 항상 새 트랜잭션을 생성하고, 기존 트랜잭션을 일시 중단합니다. |
SUPPORTS | 트랜잭션이 존재하면 참여하고, 없으면 트랜잭션 없이 실행합니다. |
NOT_SUPPORTED | 트랜잭션 없이 실행하며, 기존 트랜잭션을 일시 중단합니다. |
MANDATORY | 반드시 기존 트랜잭션이 있어야 하며, 없으면 예외를 발생시킵니다. |
NEVER | 트랜잭션 없이 실행하며, 트랜잭션이 존재하면 예외를 발생시킵니다. |
NESTED | 중첩 트랜잭션을 생성합니다. (savepoint를 사용하여 롤백 범위를 조정할 수 있음) |
2) readOnly
트랜잭션이 읽기 전용임을 선언합니다. 데이터베이스가 최적화하도록 힌트를 제공합니다.
@Transactional(readOnly = true)
public List<User> getUsers() {
return userRepository.findAll();
}
- 장점: 읽기 전용 트랜잭션은 변경 작업을 막아 데이터 일관성을 유지하고 성능을 최적화합니다.
- 주의: readOnly = true 상태에서는 변경 작업(INSERT, UPDATE, DELETE)이 발생하면 예외가 발생할 수 있습니다.
3) timeout
트랜잭션이 몇 초 동안 실행될 수 있는지 제한합니다. 제한 시간이 초과되면 롤백됩니다.
@Transactional(timeout = 5)
public void someTransactionalMethod() {
// 5초 내에 완료되지 않으면 트랜잭션 롤백
}
4) rollbackFor / noRollbackFor
- 특정 예외 발생 시 롤백할지 여부를 지정합니다.
롤백 조건 설정
@Transactional(rollbackFor = CustomException.class)
public void someTransactionalMethod() {
// CustomException 발생 시 롤백
}
롤백하지 않는 조건 설정
@Transactional(noRollbackFor = IllegalArgumentException.class)
public void someTransactionalMethod() {
// IllegalArgumentException 발생 시 롤백하지 않음
}
5) transactionManager
특정 트랜잭션 관리자를 지정합니다. 주로 복수의 데이터 소스를 사용할 때 유용합니다.
@Transactional(transactionManager = "customTransactionManager")
public void someTransactionalMethod() {
// 특정 트랜잭션 매니저 사용
}
6) value
@Transactional 애노테이션은 value 속성으로 트랜잭션 설정을 참조할 수도 있습니다.
정리
- isolation은 트랜잭션 격리 수준을 설정하여 데이터 일관성을 보장합니다.
- 다른 옵션(propagation, readOnly, timeout, rollbackFor 등)을 통해 트랜잭션 동작을 세밀하게 제어할 수 있습니다.
- 프로젝트에 따라 적절한 설정을 선택하여 성능과 데이터 무결성을 동시에 유지해야 합니다.
'Spring > Spring JPA' 카테고리의 다른 글
Cascade(영속성 전이) (2) | 2024.12.27 |
---|---|
[JPA] @Transactional의 propagation 속성 자세히 (0) | 2024.12.26 |
[JPA] @DynamicUpdate 간단히 (1) | 2024.12.26 |
[JPA]Spring에서 트랜잭션 롤백(RuntimeException, Checked Exception) (2) | 2024.12.09 |
[JPA] 영속성 캐시(Persistence Context) (1) | 2024.12.05 |