트랜잭션
여러개의 작업들을 하나의 그룹으로 묶어서 처리하는 처리 단위
ACID 원칙
- 원자성 : 작업을 더이상 쪼갤 수 없음
- 일관성 : 트랜잭션이 에러없이 성공적으로 종료될 경우, 비즈니스 로직에서 의도하는대로 일관성있게 저장되거나 변경되는 것
- 고립성 : 여러 개의 트랜잭션이 실행될 경우 각각 독립적으로 실행이 되어야 함
- 지속성 : 데이터베이스가 종료되어도 데이터는 물리적인 저장소에 저장되어 지속적으로 유지되어야 함
애너테이션 방식의 트랜잭션 적용
@Service
@Transactional // 해당 클래스에서 MemberRepository의 기능을 이용하는 모든 메서드에 트랜잭션이 추가 됨
public class MemberService {
private final MemberRepository memberRepository;
public MemberService(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
public Member createMember(Member member) {
verifyExistsEmail(member.getEmail());
return memberRepository.save(member);
}
}
클래스 레벨과 메서드 레벵의 트랜잭션 적용 순서
- 클래스 레벨에만 @Transactional이 적용된 경우
▶ 클래스 레벨의 @Transactional 애너테이션이 메서드에 일괄 적용
- 클래스 레벨과 메서드 레벨에 함께 적용된 경우
▶ 메서드 레벨의 @Transactional 애너테이션이 적용됨
여러 작업이 하나의 트랜잭션으로 묶이는 경우
@Transactional
@Service
public class OrderService {
...
...
private void updateStamp(Order order) {
...
memberService.updateMember(member); // updateMember 호출
}
}
@Transactional
@Service
public class MemberService {
...
...
@Transactional(propagation = Propagation.REQUIRED) // 현재 진행 중인 트랜잭션이 존재하며 해당 트랜잭션 사용 / 존재하지 않으면 새 트랜잭션 생성
public Member updateMember(Member member) {
...
return memberRepository.save(findMember);
}
}
트랜잭션 전파
- Propagation.REQUIRED : 진행중인 트랜잭션이 없으면 생성 / 진행중인 트랜잭션이 있으면 참여
- Propagation.REQUIRES_NEW : 이미 진행중인 트랜잭션과 무관하게 새로운 트랜잭션 생성
- Propagation.MANDATORY : 진행중인 트랜잭션이 없으면 생성 / 진행중인 트랜잭션이 있으면 예외발생
- Propagation.NOT_SUPPORTED : 트랜잭션을 필요로 하지 않음 / 진행중인 트랜잭션이 있으면 중단하고 실행
- Propagation.NEVER : 트랜잭션이 필요로 하지 않음 / 진행중인 트랜잭션이 있으면 예외발생
트랜잭션 격리 레벨
- Isolation.DEFAULT: 데이터베이스에서 제공하는 기본 값
- Isolation.READ_UNCOMMITTED: 다른 트랜잭션에서 커밋하지 않은 데이터를 읽는 것을 허용
- Isolation.READ_COMMITTED: 다른 트랜잭션에 의해 커밋된 데이터를 읽는 것을 허용
- Isolation.REPEATABLE_READ: 트랜잭션 내에서 한 번 조회한 데이터를 반복해서 조회해도 같은 데이터가 조회되도록
- Isolation.SERIALIZABLE: 동일한 데이터에 대해서 동시에 두 개 이상의 트랜잭션이 수행되지 못하도록