Transactional의 Propagation, Isolation

고승원·2023년 7월 12일
0

Spring

목록 보기
11/14

@Transactional 어노테이션은 메서드에 트랜잭션을 만들어 준다. 여러가지 속성을 설정할 수 있는데 읽기 전용 트랜잭션, 전파 레벨, 격리 레벨, 타임 아웃, 롤백 규칙 등을 설정해줄 수 있다.

Spring 에서 전파와 격리 레벨에 대해서 알아보자.

Propagation

트랜잭션이 진행중일 때 추가되는 트랜잭션을 어떻게 처리할지 결정하는 방법을 뜻한다.

REQUIRE

Default 설정이며 실행중인 트랜잭션이 있으면 추가되고, 없으면 새로운 트랜잭션을 만든다.

SUPPORTS

실행중인 트랜잭션이 있으면 추가되고, 없으면 트랜잭션 없이 실행된다.

MANDATORY

실행중인 트랜잭션이 있으면 추가되고, 없으면 Exception을 반환한다.

NEVER

실행중인 트랜잭션이 있으면 Exception을 반환하고, 없으면 트랜잭션 없이 실행된다.

NOT_SUPPORTED

실행중인 트랜잭션이 있으면 잠시 보류시킨 후 트랜잭션 없이 실행하고, 없으면 트랜잭션 없이 실행된다.

REQUIRES_NEW

실행중인 트랜잭션이 있으면 잠시 보류시킨 후 새로운 트랜잭션을 만들고, 없으면 새로운 트랜잭션을 만든다.

NESTED

실행중인 트랜잭션이 있으면 Point를 만들고(에러 발생시 Point로 Rollback된다.), 없으면 새로운 트랜잭션을 만든다.

코드

그렇다면 스프링에선 어떻게 관리되고 있는 것일까? 코드와 함께 알아보자.

Spring에서 @Transactional을 사용하는 경우 TransactionManager인터페이스를 상속받는 PlatformTransactionManager가 있다. PlatformTransactionManager는 Spring 트랜잭션의 필수 인터페이스라고 설명이 되어있다.

본인은 JPA를 사용했기 때문에 PlatformTransactionManager를 상속받는 AbstractPlatformTransactionManager를 상속받은 JPATransactionManager를 사용한다.

JPATransactionManager의 메서드를 모두 살펴보았지만 TransactionDefinition외에 Propagation, Isolation에 대한 내용이 없었다. 그래서 AbstractPlatformTransactionManager를 살펴보았다.

트랜잭션이 있는 경우 handlerExistingTransation 메소드를 호출한다.
그렇지 않은 경우 TIME OUT 여부를 확인하고, Propagation 레벨에 대해서 처리한다.

위에 적은 것 처럼 NEVER인 경우 IllegalTransactionStateException을 반환하고 다른 레벨에 대해서 적절히 처리하는 모습이다.

Isolation

트랜잭션이 동시에 수행될때 다른 트랜잭션이 동일한 데이터에 대해서 어떻게 할 수 있는지에 대한 격리 레벨을 뜻한다.


참고

  • Dirty Read: 현재 트랜잭션에서 커밋하지 않은 데이터를 다른 트랜잭션이 조회할 수 있다.
  • Non-Repeatable Read: 한 트랜잭션에서 같은 쿼리를 두 번 실행했을 때 결과값이 다른 경우 (여러 스냅샷 사용)
  • Phantom read: 다른 트랜잭션이 데이터를 추가/삭제하면 없던 데이터가 생기거나 있던 데이터가 사라지는 현상

DEFAULT

Default는 DBMS의 isolation level을 따라간다.
Mysql은 REPEATABLE READ가 기본 설정이다.
그외 대부분의 DBMS는 READ_COMMIT이 기본 설정이다.

READ_UNCOMMITTED

트랜잭션의 Commit, Rollback 여부에 상관없이 다른 트랜잭션이 값을 조회할 수 있다.
Dirty Read, Non-Repeatable Read, Phantom Read 현상이 모두 발생한다.

READ_COMMITTED

Commit한 데이터는 읽을 수 있다.
Dirty Read 현상은 일어나지 않지만, Non-Repeatable Read 현상과 Phantom Read 현상이 발생한다.

REPEATABLE_READ

트랜잭션에 ID를 부여하여 조회하려는 트랜잭션 ID보다 작은 트랜잭션에서 변경한 내용만 읽는다.
Dirty Read, Non-Repeatable 현상이 일어나지 않지만, Phantom Read현상이 발생한다.

SERIALIZABLE

모든 트랜잭션을 순차적으로 수행하는 방법이다. 동시성 문제는 없지만, 성능이 매우 떨어지게 된다.


위의 내용이 자세히 이해가 안될수 있다. 여기에 그림과 함께 정리해둬서 보기 좋으니 참고하길 바란다.

코드

Isolation Level은 AbstractPlatformTransactionManager의 getTransaction 메서드에서 TransactionDefinition 객체에 담겨 startTransaction 메서드에 전달된다.

위에서 언급한 handleExistingTransaction 메서드의 하단 부분이다.
isValidateExistingTransaction은 Transaction Isolation 속성을 무시하는 flag이고 true인 경우 Default 설정으로 적용된다.

currentIsolationLevel이 null이거나 호환하지 않는 경우 에러를 반환한다.

profile
봄은 영어로 스프링

0개의 댓글