개발/spring

[jpa] transaction propagation

방푸린 2024. 5. 23. 13:52
반응형

2024.05.23 - [개발/spring] - [transaction] isolation level

 

[jpa] transaction isolation level

2024.05.22 - [개발/sql] - DB isolation level DB isolation levelisolation level 이란 무엇인가?디비 동시성을 관리하고 데이터 정합성을 유지하기 위해 서로 다른 트랜젝션끼리의 관계를 정의한 것 존재 이유?언

bangpurin.tistory.com

A transaction is a group of sequential operations on a database that forms a logical unit of working with data.

Transactions are used to maintain the consistency and integrity of data in a database.

 

 It’s important to know that transactions are thread-local, so they apply to the current thread only.

 

propagation: 세션의 트랜젝션을 어떻게 이용할지; 무결성과 정합성을 유지하기 위한 방법

종류 트랜젝션 존재 시 트랜젝션 미존재 시 비고
REQUIRED 기존 트랜잭션 이용 신규 트랜잭션 생성 기본값
SUPPORTS 기존 트랜잭션 이용  트랜잭션 없이 수행  
MANDATORY 기존 트랜잭션 이용 exception 발생 꼭 이전 트랜잭션이 있어야 하는  경우
NEVER exception 발생 정상적으로 트랜잭션 없이 수행 트랜잭션 없을 때만 작업이 진행되어야할 때
NOT_SUPPORTED 기존 트랜젝션은 중지하고 대기, 트랜젝션 없이 실행하다가 끝나면 기존 트랜젝션 실행 트랜잭션 없이 로직 수행 기존 트랜잭션에 영향을 주지 않아야할 때
REQUIRES_NEW 현재 트랜잭션은 중지되고 대기. 새로운 트랜잭션을 생성하고 종료되면 현재 트랜젝션이 다시 진행 신규 트랜잭션을 생성하고 로직을 실행 이전 트랜잭션과 구분하여 새로운 트랜잭션으로 처리가 필요할 때;
락과 함께 사용할 경우 데드락 조심
NESTED 현재 트랜잭션에 Save Point를 걸고 이후 트랜잭션을 수행 REQUIRED와 동일하게 작동
(신규 트랜잭션을 생성하고 로직이 수행)
DBMS특성에 따라 지원 혹은 미지원;
jpa에서 사용 불가
  • Nested is not possible in the JPA dialect because you cannot create a save point here. Nested, unlike Required New, creates a kind of save point. For example, if you are updating a huge batch of data, you won’t have to roll back everything in case of an error; you may roll back just to the save point.

 

두 함수간 트랜젝션을 전파하는 경우(출처: chat gpt..)

부모 함수 -> 자식 함수라고 가정할 때

트랜잭션 전파의 핵심은 부모 메서드에서 트랜잭션이 이미 시작되었는지 여부입니다. parentMethod()에서 트랜잭션이 시작되었다면, 그 안에서 호출되는 모든 자식 메서드(접근 제어자 public이든 private이든 상관없이)는 동일한 트랜잭션 경계 내에서 실행됩니다.

부모 자식 부모 transaction 전파 여부
public + @Transactional private in same class  O
public + @Transactional public in same class, @Transactional유무 상관없이 O
public + @Transactional public in different class, @Transactional유무 상관없이 O

1. Transaction은 public에서 시작, private은 함수의 일부라 판단하여 트랜젝션 이어짐

@Service
public class MyService {

  @Transactional
  public void parentMethod() {
    // Transaction starts here
    privateChildMethod(); // This method is part of the same transaction
  }

  private void privateChildMethod() {
    // This method participates in the transaction started by parentMethod
  }
}

2. 자식 함수가 같은 클래스에 있으면 부모 트랜젝션 전파됨

만약 반대로 부모가 @TRANSACTIONAL이 없고 같은 클래스의 자식에게 @TRANSACTIONAL이 있다면 자식의 트랜젝션은 신규로 생성되지 않음(프록시를 타지 않아서)

@Service
public class MyService {

  @Transactional
  public void parentMethod() {
    // Transaction starts here
    publicChildMethod(); // This call bypasses the proxy
  }

  public void publicChildMethod() {
    // This method does not participate in the transaction started by parentMethod
  }
}

3. 부모와 자식 클래스가 다를 경우, 자식이 기본 Transaction을 사용할 경우

클래스가 다를 경우 자식 함수가 proxy의 영향을 받기 때문에 부모의 트랜젝션이 자식에게 전파된다.

자식 함수가 @Transaction 어노테이션이 있건 없건 전파되는데, 만약 자식 함수도 Transaction 어노테이션이 있고 별다른 propagation 설정이 없다면 기본 전파 옵션이 Propagation.REQUIRED 이기 때문에 기존 트랜젝션을 탄다. 이 경우가 transaction 중첩이 가능한 부분이고, 위 옵션에 따라 달라진다.

@Service
public class ParentService {

  @Autowired
  private ChildService childService;

  @Transactional
  public void parentMethod() {
    // Transaction starts here
    childService.childMethod(); // This call goes through the proxy
  }
}

@Service
public class ChildService {

  @Transactional //있건없건 트랜젝션 영향 받음
  public void childMethod() {
    // This method participates in the transaction started by parentMethod
    // because the call goes through the Spring proxy
  }
}

https://www.baeldung.com/spring-transactional-propagation-isolation

한 번쯤 읽어볼 만한 시행착오

https://technixc.medium.com/how-to-use-transactional-annotation-like-a-pro-4129308ad069

728x90
반응형