Spring

[Spring] Spring Transaction 세부 설정 설명

오잎 클로버 2022. 2. 21. 11:50
728x90

이 글은 이 글과 연결되어 있습니다! 참고해주세요.

 

Spring 트랜잭션에는 4가지의 세부 설정이 가능합니다.

  • 트랜잭션 전파
  • 격리 수준
  • 제한 시간
  • 읽기 전용

트랜잭션 전파

트랜잭션의 경계에서 이미 진행 중인 트랜잭션이 있거나 없을 때 어떻게 작동할 것인가를 결정하는 방식을 의미합니다.

Spring이 지원하는 전파 속성은 다음의 7가지가 있습니다.

  • REQUIRED
  • SUPPORTS
  • MANDATORY
  • REQUIRES_NEW
  • NOT_SUPPORTED
  • NEVER
  • NESTED

저도 자세히는 모르기때문에 간략하게만 설명하도록 하겠습니다;; 자세히 아시는 분들은 댓글 달아주시면 감사하겠습니다..

1. REQUIRED

 

default 속성으로 모든 트랜잭션 매니저가 지원하며, 대개 이 속성을 사용합니다.

미리 시작된 트랜잭션이 참여하고 없으면 새로 시작하는 속성입니다.

하나의 트랜잭션이 시작된 후 다른 트랜잭션 경계가 설정된 메소드를 호출하게 되면, 자연스럽게 같은 트랜잭션으로 

묶입니다.

2. SUPPORTS

이미 시작 트랜잭션이 있으면 참여하고, 그렇지 않으면 트랜잭션 없이 진행하는 속성입니다.

트랜잭션이 없기는 하지만 해당 경계안에서 Connection객체나 Session 등은 공유할 수 있습니다.

3. MANDATORY

이미 시작 트랜잭션이 있으면 참여합니다. 하지만 트랜잭션이 시작된 것이 없으면, 새로 시작하는 대신

예외를 발생시키는 속성입니다.

즉, 혼자서 독립적으로 진행하면 안되는 경우에 사용할 수 있습니다.

4. REQUIREDS_NEW

항상 새로운 트랜잭션을 시작하는 경우에 사용할 수 있습니다. 만약 이미 시작된 트랜잭션이 있으면,

잠시 보류시키는 속성입니다. 

5. NOT_SUPPORTED

이미 진행 중인 트랜잭션이 없으면 이를 보류시키고, 트랜잭션을 사용하지 않도록하는 속성입니다.

6. NEVER

이미 진행 중인 트랜잭션이 있으면 예외를 발생시키며, 트랜잭션을 사용하지 않도록 강제하는 속성입니다.

7. NESTED

이미 진행 중인 트랜잭션이 있으면 중첩 트랜잭션을 시작하는 속성입니다.

중첩 트랜잭션은 트랜잭션 안에 새로운 트랜잭션을 만드는 것으로, 독립적인 트랜잭션을 만드는 REQUIREDS_NEW와는 다릅니다. 중첩 트랜잭션은 먼저 시작된 부모 트랜잭션의 커밋과 롤백에는 영향을 받지만, 자신의 커밋과 롤백은

부모 트랜잭션에게 영향을 주지 않습니다.

(중첩 트랜잭션을 지원하지않는 트랜잭션 매니저들이 있기때문에 적용이 되지않을 수 있습니다.)

 

 

해당 속성을 지원하지않는 트랜잭션 매니저와 데이터 액세스 기술이 있을 수 있으므로 변경이 필요한 경우,

별도의 설정이 필요한 지 확인 후 적용을 해야합니다.

격리 수준

동시에 여러 트랜잭션이 진행될 때 트랜잭션의 작업 결과를 여타 트랜잭션에게 어떻게 노출할 것인지 결정합니다.

Spring은 다음의 5가지 격리수준 속성을 지원합니다.

 

  • DEFAULT
  • READ_UNCOMMITTED
  • READ_COMMITTED
  • REPEATABLE_READ
  • SERIALIZABLE

1. DEFAULT

데이터 액세스 기술 혹은 DB 드라이버의 디폴트 설정을 따르는 속성입니다. 

대부분의 DB는 READ_COMMITTED를 기본 격리 수준으로 갖습니다. 물론 일부 DB는 디폴트 값이 다른 경우가 있기에

DEFAULT로 사용할 경우 드라이버와 DB 문서를 참고해서 기본 격리 수준을 확인해야합니다.

2. READ_UNCOMMITTED

가장 낮은 격리 수준이며, Spring은 기본적으로 DEFAULT로, DB는 일반적으로 READ_COMMITTED이기때문입니다.

하나의 트랜잭션이 커밋되기 전에 그 변화가 다른 트랜잭션에 그대로 노출됩니다.

하지만 가장 빠르기 때문에 데이터의 일관성이 조금 떨어지더라도 성능을 극대화할 때 의도적으로 사용하기도 합니다.

3. READ_COMMITTED

가장 많이 사용되는 격리 수준으로, 다른 트랜잭션이 커밋하지않은 정보는 읽을 수 없습니다.

대신 하나의 트랜잭션이 읽은 로우(ROW)를 다른 트랜잭션이수정할 수 있습니다.

처음 트랜잭션이 같은 로우를 다시 읽을 때 다른 내용이 발견될 수도 있습니다.

4. REPEATABLE_READ

하나의 트랜잭션이 읽은 로우를 다른 트랜잭션이 수정할 수 없도록 막아줍니다.

하지만 새로운 로우를 추가하는 것은 막지않습니다.

따라서 SELECT로 조건에 맞는 모든 로우를 전부 가져오는 경우, 트랜잭션이 끝나기 전에 추가된 로우가 발견될 수 도 있습니다.

5. SERIALIZABLE

가장 강력한 트랜잭션 격리 수준으로 이름 그대로 트랜잭션을 순차적으로 진행시켜줍니다.

그렇기에 여러 트랜잭션이 동시에 같은 테이블의 정보를 액세스할 수 없습니다.

가장 안전한 동시에 가장 성능이 떨어지기에 극단적으로 안전한 작업이 필요한 경우가 아니라면 사용해서는 안됩니다.

읽기 전용

readOnly는 성능 최적화와 쓰기 방지를 목적으로 사용할 수 있습니다.

  • 읽기 전용으로 설정함으로써 성능을 최적화합니다.
  • 쓰기 작업이 일어나는 것을 의도적으로 방지합니다.

일부 트랜잭션 매니저들이 읽기전용을 무시하고 쓰기 작업을 허용할 수 도 있기에 주의해야합니다.

일반적으로 INSERT, UPDATE, DELETE의 작업을 수행하게 되면, 예외가 발생하게 됩니다.

Rollback/Commit 예외

런타임 예외가 발생하게 되면 롤백하고, 예외가 발생하지 않았거나 체크 예외가 발생하였다면 커밋합니다.

여기서 체크 예외를 커밋 대상으로 삼은 이유는 체크 예외는 예외적인 상황보다는 반환값을 대신해주는

비지니스적인 의미를 담은 결과로 많이 사용되기 때문입니다.

Spring은 데이터 액세스 기술의 예외는 런타임 예외로 전환하여 던지므로 런타임 예외만 롤백 대상으로 삼은 것입니다.

 

하지만 롤백/커밋의 동작 방식의 변경을 원한다면 설정을 통해 변경이 가능합니다.

커밋대상이지만 롤백을 발생시킬 예외나 클래스 이름은 각각 rollbackFor 또는 rollbackForClassName으로 지정할 수 있습니다. 반대로 롤백 대상인 런타임 예외를 트랜잭션 커밋 대상으로 지정하기 위해서는 noRollbackFor 또는 noRollbackForClassName을 이용할 수 있습니다.

 

제한 시간

timeout 속성을 이용하면 트랜잭션에 제한시간을 지정할 수 있습니다.

값은 int 타입의 초 단위로 지정할 수 있는데 문자열로 지정하기를 원한다면 timeoutString을 사용하면 됩니다.

만약 별도로 값을 설정해주지 않는다면 트랜잭션 시스템의 제한시간을 따르며,

제한 시간을 직접 지정했는데 트랜잭션 매니저에서 이 기능을 지원하지 못한다면 예외가 발생할 수 있습니다.

 

 

이상입니다.

'Spring' 카테고리의 다른 글

[Spring] AOP 예제  (0) 2022.03.14
[Spring] DTO vs VO  (0) 2022.02.28
[Spring] Spring Transaction 특징 및 핵심기술 설명  (0) 2022.02.20
[Spring] Spring AOP/PSA 설명  (0) 2022.02.19
[Spring] Spring POJO 설명  (0) 2022.02.18