Spring AOP - Transactional, Async
- study
- 2022. 3. 25. 22:55
Transactional 전파레벨 관련 실험
실험 환경
- 로컬에서 docker를 띄워 Slave, Master DB를 구성하였다.
- Read-Only True시 Slave DB와 연결, Read-Only False시 Master DB와 연결 하도록 구성
Transactional Read-Only False 메소드 안에서 Read-Only True인 메소드가 실행된다면?
- 호출 한 메소드 (Read-Only False)에서 연결 된 Master DB와의 Connection을 사용한다.
- 즉, 조회 쿼리 (Read-Only True)도 Slave를 찌르지 않고, Master DB와의 커넥션을 통해 가져오게 된다.
Transactional Read-Only True 메소드 안에서 Read-Only False인 메소드가 실행된다면?
- Connection is read-only. Queries leading to data modification are not allowed. 에러 발생
Transaction 전파 레벨
- Propagation.REQUIRED
- 스프링의 기본 전파 레벨
- 해당 전파레벨의 메소드를 호출한 곳에서 별도의 트랜잭션이 설정되어 있지 않았다면 트랜잭션을 새로 시작
- 호출한 곳에서 이미 트랜잭션이 설정되어 있다면 기존의 트랜잭션 내에서 로직을 실행
- 예외가 발생하면 롤백이 되고 호출한 곳에도 롤백이 전파
지금까지는 Propagation.REQUIRED로 실행이 되어왔기 때문에, 부모의 트랜잭션 내에서 로직을 실행하였다.
REQUIRED_NEW로 전파레벨을 바꾸어본다면?
- 예외가 발생하지 않고 별개의 커넥션이 생성되었다.
- Propagation.REQUIRED_NEW
- 매번 새로운 트랜잭션을 시작
- 새로운 트랜잭션 안에서 예외가 발생해도 호출한 곳에는 롤백이 전파되지 않음
- 생성된 트랜잭션들은 완전히 독립된 별개의 단위로 작동
Spring AOP - Transactional
@Transactional이 없는 메소드에서 자신의 @Transactional이 붙은 메서드를 실행
- JPA의 변경감지가 일어나지 않았다.
- 변경감지
- Transaction을 Commit하는 순간 영속성 컨텍스트에 있는 엔티티의 변경을 감지
- Transaction이 걸리지 않았다.
@Transactional이 없는 메소드에서 외부 @Transactional이 붙은 메서드를 실행
- JPA의 변경감지가 일어났다.
트랜잭션의 동작 원리
- 스프링 @Transactional은 Proxy를 통해 처리 된다.
- 트랜잭션 어노테이션이 걸려있는 메소드의 클래스의 프록시 객체가 만들어진다.
- 프록시 객체의 update에서 트랜잭션 비긴, 커밋, 롤백과 같은 작업이 이루어진다.
- 같은 클래스 내의 메소드를 호출 한 경우 "프록시객체"를 타지 않는다.
- 자신의 클래스에 있는 update 메소드를 호출한다.
- 반면 외부에 있는 메소드를 호출했을 때는 프록시 객체를 타게된다.
Async 관련 실험
Read-Only False 메소드에서 @Async로 Read-Only True 메소드를 실행 할 경우
- http-nio-8080-exec-1 쓰레드와, task-1 (@Async)쓰레드가 생성되었다.
- 그리고 각 쓰레드마다 커넥션이 새로 생성되었으며 Transactional Read-Only 설정에 따라 Master, Slave로 연결이 되었다.
@Async Read-Only False 메소드에서 Read-Only True 메소드를 실행
- task-1 쓰레드가 생성되었다.
- 해당 쓰레드에서 가져온 커넥션 (Read-Only False 이기 때문에 Master)로 Read-Only True 메소드인 getUser()가 실행되었다.
Read-Only True에서 @Async Read-Only Ture 메소드 실행
- 기존 쓰레드 http-nio-8080-exec-2의 커넥션과 task-2의 커넥션이 별도로 생성된다.
- 둘 다 Read-Only True여서 Slave DB와 연결되었다.
Spring AOP - Async
일반 메소드에서 @Async 붙은 메소드를 실행 (같은 클래스)
- 세 메소드가 전부 http-nio-8080-exec6 스레드에서 실행된다.
- 같은 클래스 내에서 실행한 @Async가 무시되었다.
@Async 붙은 메소드에서 @Async 붙은 메소드를 실행 (같은 클래스)
- 세 메소드가 전부 task-3 스레드에서 실행된다.
- 같은 클래스 내에서 실행한 @Async들이 무시가 되었다.
결론
- 같은 클래스 내에서 AOP로 동작하는 어노테이션들 (Transactional, Async)의 호출을 주의하자
'study' 카테고리의 다른 글
Spring에서 X-Forwarded-For 값을 가져오는 2가지 방법 (2) | 2022.05.22 |
---|---|
서킷브레이커 (0) | 2022.04.13 |
[Java]LocalDateTime, OffsetDateTime, ZonedDateTime, Instant (0) | 2022.03.16 |
[Java]컬렉션(Collections) 정리 (0) | 2021.12.02 |
[Spring]프로토타입과 스코프 (0) | 2021.12.02 |