JAVA 정리노트
Spring, 중첩 트랜잭션(Nested Transaction)
Dodledd
2024. 10. 8. 17:13
트랜잭션(Transaction)
데이터베이스의 상태를 변화시키기 위한 일련의 작업을 하나로 묶은 논리적 단위입니다.
이 논리적 작업 단위는 모두 성공적으로 완료되거나,
하나라도 실패하면 전체 작업이 취소되도록 보장하는 것이 핵심입니다.
ACID 원칙
- Atomicity (원자성)
- 트랜잭션은 하나의 단위로 실행되며, 모든 작업이 성공적으로 완료되거나 모두 실패하여 데이터베이스에 전혀 반영되지 않아야 합니다.
- 예를 들어, 은행에서 A 계좌에서 B 계좌로 돈을 이체할 때, A 계좌에서 돈이 빠져나가고 B 계좌에 돈이 입금되는 작업이 하나의 트랜잭션으로 묶여야 합니다. 만약 중간에 오류가 발생하면, 모든 작업이 취소되어야 합니다.
- Consistency (일관성)
- 트랜잭션이 성공적으로 완료된 후 데이터베이스는 항상 일관된 상태를 유지해야 합니다. 일관성 있는 상태란 데이터베이스에 저장된 데이터가 모든 제약 조건을 만족하는 상태입니다.
- 예를 들어, 은행 계좌에 음수 잔고가 발생하지 않도록 하는 규칙이 있다면, 트랜잭션이 끝난 후에도 이 규칙이 유지되어야 합니다.
- Isolation (격리성)
- 트랜잭션은 다른 트랜잭션과 독립적으로 실행되어야 하며, 동시에 여러 트랜잭션이 실행되더라도 서로 간섭하지 않아야 합니다.
- 즉, 하나의 트랜잭션이 완료되기 전까지는 다른 트랜잭션이 그 트랜잭션이 수정 중인 데이터를 볼 수 없습니다. 이를 통해 다중 사용자가 동시에 데이터를 수정하는 상황에서도 데이터 무결성이 보장됩니다.
- Durability (지속성)
- 트랜잭션이 성공적으로 완료되면, 그 결과는 영구적으로 데이터베이스에 저장되어야 하며, 시스템 장애가 발생하더라도 손실되지 않아야 합니다.
- 예를 들어, 전원이 꺼지거나 시스템 오류가 발생하더라도, 완료된 트랜잭션의 결과는 데이터베이스에 그대로 남아 있어야 합니다.
트랜잭션의 생명주기
- BEGIN: 트랜잭션이 시작됩니다.
- COMMIT: 트랜잭션이 성공적으로 완료되었음을 데이터베이스에 알리고, 변경 사항을 영구적으로 저장합니다.
- ROLLBACK: 트랜잭션 중 오류가 발생하거나 취소 요청이 있으면, 트랜잭션 내에서 수행된 모든 작업을 취소하고 이전 상태로 되돌립니다.
Spring 에서는 어노테이션을 메서드나 클래스에 붙여서 적용시킵니다.
@Transactional
public void someMethod() {
// 트랜잭션 내에서 실행될 코드
}
트랜잭션 전파(Propagation)
트랜잭션 전파는 트랜잭션이 이미 진행 중일 때 새로운 트랜잭션이 어떻게 동작할지를 정의합니다.
가장 큰 예로 중첩 트랜잭션이 있습니다.
중첩 트랜젝션을 설명하기전에 먼저 전파 옵션에 대해 알아보겠습니다.
주요 전파 옵션
- REQUIRED: 기본 값으로, 기존 트랜잭션이 있으면 그 트랜잭션에 참여하고, 없으면 새로운 트랜잭션을 시작합니다.
- REQUIRES_NEW: 항상 새로운 트랜잭션을 시작하고, 기존 트랜잭션이 있으면 이를 일시 중단합니다.
- SUPPORTS: 트랜잭션이 있으면 그 트랜잭션에 참여하고, 없으면 트랜잭션 없이 실행됩니다.
- MANDATORY: 이 전파 방식은 반드시 트랜잭션이 있어야만 동작합니다. 만약 트랜잭션이 없으면 예외가 발생합니다.
- PROPAGATION_NEVER: 이 전파 방식은 트랜잭션이 존재하지 않을 때만 동작합니다. 만약 트랜잭션이 있으면 예외가 발생합니다.
outher
@Service
public class TransactionService {
@Autowired
private SubTransactionService subTransactionService;
// 전파 옵션: REQUIRED
@Transactional(propagation = Propagation.REQUIRED)
public void outerTransaction() {
System.out.println("Outer Transaction Start");
// 데이터베이스에 어떤 작업 수행
subTransactionService.innerTransaction(); // 내부 메서드 호출
System.out.println("Outer Transaction End");
}
}
inner
@Service
public class SubTransactionService {
// 전파 옵션: REQUIRES_NEW
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void innerTransaction() {
System.out.println("Inner Transaction Start");
// 데이터베이스에 어떤 작업 수행
System.out.println("Inner Transaction End");
}
}
회사에서 자주 사용하는 전파옵션
- NOT_SUPPORTS: 트랜잭션이 존재하면 그 트랜잭션을 일시 중단하고, 트랜잭션 없이 메서드를 실행합니다.
즉, 위의 전파옵션은 항상 독립적으로 실행되고 상위 트렌젝션의 영향을 받지만 하위 트렌젝션에게 영향을 끼치지는 않습니다.
예시 : RbckbrkdService
//롤백처리관리자_재처리
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public int rollBackProc_RE(MData param) throws MEPSException
{
}