티스토리 뷰

JPA Propagation, Isolation 알아보기

  • jpa @Transactional 에는 2가지 중요 옵션을 사용할 수 있다.
    • propagation: 이는 세션의 트랜잭션을 어떻게 이용할지에 대한 설정이다.
      • REQUIRED, SUPPORTS, MANDATORY, NEVER, NOT_SUPPORTED, REQUIRES_NEW, NESTED 가 있다.
    • isolation: JPA상에서 DB Isolation을 지정할 수 있다.
      • DEFAULT, READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE 가 있다.

Transaction Propagation

  • Propagation은 트랜잭션의 영역, 바운더리를 지정하기 위한 설정이다.

Propagation 정리

종류트랜잭션존재트랜잭션미존재비고

REQUIRED 기존 트랜잭션 이용 신규 트랜잭션 생성 기본설정이다
SUPPORTS 기존 트랜잭션 이용 트랜잭션 없이 수행  
MANDATORY 기존 트랜잭션 이용 Exception 발생 꼭 이전트랜잭션이 있어야 하는경우
NEVER exception이 발생한다 정상적으로 트랜잭션 없이 수행 트랜잭션 없을때만 작업이 진행되어야할때
NOT_SUPPORTED 트랜잭션이 종료될 때 까지 대기한 후 트랜잭션이 종료되고 나면 실행 트랜잭션 없이 로직이 수행 기존 트랜잭션에 영향을 주지 않아야할때 사용된다.
REQUIRES_NEW 현재 트랜잭션이 종료될 때 까지 대기한 후 새로운 트랜잭션을 생성하고 실행 신규 트랜잭션을 생성하고 로직을 실행 이전트래잭션과 구분하여 새로운 트랜잭션으로만 처리가 필요할때 사용
NESTED 현재 트랜잭션에 Save Point를 걸고 이후 트랜잭션을 수행 REQUIRED와 동일하게 신규 트랜잭션을 생성하고 로직이 수행 DBMS특성에 따라 지원 혹은 미지원

REQUIRED

  • REQUIRED는 기본 Propagation이다.
  • 트랜잭션 존재시: 기존 트랜잭션 이용
  • 트랜잭션 미 존재시: 신규 트랜잭션 생성

사용예

@Transactional(propagation = Propagation.REQUIRED)
public void writeData(Data data) {...}

// or

@Transactional
public void writeData(Data data) {...}

SUPPORTS

  • SUPPORTS는 현재 활성화된 트랜잭션이 있는지 검사한다.
  • 트랜잭션 존재시: 기존 트랜잭션 이용
  • 트랜잭션 미 존재시: 트랜잭션 없이 수행
@Transactional(propagation = Propagation.SUPPORT)
public void writeData(Data data) {...}

MANDATORY

  • 트랜잭션이 필수적으로 필요한 propagation이다.
  • 트랜잭션 존재시: 기존 트랜잭션 이용
  • 트랜잭션 미 존재시: exception이 발생한다.
@Transactional(propagation = Propagation.MANDATORY)
public void writeData(Data data) {...}

NEVER

  • 트랜잭션이 없어 로직을 수행한다.
  • 트랜잭션 존재시: exception이 발생한다.
  • 트랜잭션 미 존재시: 정상적으로 수행된다. (즉, 트랜잭션 없이 수행한다.)
@Transactional(propagation = Propagation.NEVER)
public void writeData(Data data) {...}

NOT_SUPPORTED

  • 트랜잭션 존재시: 트랜잭션이 종료될 때 까지 대기한 후 트랜잭션이 종료되고 나면 실행한다.
  • 트랜잭션 미 존재시: 트랜잭션 없이 로직이 수행된다.
@Transaction(propagation = Propagation.NOT_SUPPORT)
public void writeData(Data data) {...}

REQUIRES_NEW

  • 트랜잭션 존재시: 현재 트랜잭션이 종료될 때 까지 대기한 후 새로운 트랜잭션을 생성하고 실행한다.
  • 트랜잭션 미 존재시: 신규 트랜잭션을 생성하고 로직을 실행한다.
@Transaction(propagation = Propagation.REQUIRES_NEW)
public void writeData(Data data) {...}

NESTED

  • 이 옵션은, 데이터베이스가 지원하는지 여부와, JDBC 드라이버에서 지원해 주어야 동작한다.
  • 트랜잭션 존재시: 현재 트랜잭션에 Save Point를 걸고 이후 트랜잭션을 수행한다. (즉, 이후 트랜잭션 실패시 Save Point까지 롤백되며, SAve Point이후는 트랜잭션 처리가 된다.)
  • 트랜잭션 미 존재시: REQUIRED와 동일하게 신규 트랜잭션을 생성하고, 로직이 수행된다.
@Transactional(propagation = Propagation.NESTED)
public void writeData(Data data) {...}

ISOLATION LEVEL

  • Isolation Level은 동시 트랜잭션이 수행될때 다른 트랜잭션이 동일한 데이터에 대해서 어떻게 보일지에 대한 범위를 나타낸다.

Isolation관련 용어

  • Dirty Read: 현재 트랜잭션에서 커밋되지 않은 변경 데이터를 다른 트랜잭션이 읽을 수 있음을 의미한다.
  • Nonrepeatable Read: 가장 먼저 데이터를 읽은 데이터가, 다른 트랜잭션에서 변경을 했고, 이후 다시 데이터를 읽을때 변경된 데이트를 읽을 수 있음을 의미한다. (즉, 먼저 변경한 쪽의 데이터를 다시 읽게 됨을 의미)
  • Phantom read: 다른 트랜잭션이 신규 데이터를 추가하거나, 기존 데이터를 삭제할때, 범위 쿼리를 수행하면 데이터 row가 달라지는 현상을 말한다.

DEFAULT

  • 기본 Isolation 은 DBMS에 설정한 isolation level을 따라간다.
  • Mysql은 REPEATABLE READ 가 기본 설정이다.
  • Oracle은 READ_COMMIT 이 기본 설정이다.
  • SQL Server는 READ_COMMIT 이 기본 설정이다.
  • Postgres는 READ_COMMIT 이 기본 설정이다.

READ_UNCOMMITTED Isolation

  • 가장 느슨한 isolation level이다.
  • 동시에 동일 데이터에 대해서 트랜잭션이 수행되는 경우 결과를 보장하지 못하고, 계속해서 커밋되지 않은 값을 읽을 수 있게 된다.
  • Dirty Read, Non-Repeatable Read, Phantom Read 현상이 모두 발생한다.
@Transactional(isolation = Isolation.READ_UNCOMMITTED)
public void writeData(Data data) {...}

READ_COMMITTED Isolation

  • Dirty Read가 발생하지 않는다.
  • 하나의 트랜잭션에서 커밋이 수행된 데이터는 다시 읽기를 하면 변경된 데이터를 읽게 된다.
  • 즉, Non-Repeatable Read 현상과 Phantom Read 현상이 발생한다.
@Transactional(isolation = Isolation.READ_COMMITTED)
public void writeData(Data data) {...}

REPEATABLE_READ Isolation

  • Dirty Read, Non-Repeatable Read 현상이 발생하지 않는다.
  • 즉, 커밋되지 않는 데이터에 대해서 어떠한 사이드 이펙트가 없다.
  • 데이터를 다시 읽어도 원래 데이터를 그대로 유지하게 된다.
  • 그러나 범위 검색을 수행하는 경우 새로 추가된 데이터나, 삭제된 데이터가 보이게 된다.
  • 즉, Phantom Read현상이 발생한다.
@Transactional(isolation = Isolation.REPEATABLE_READ)
public void writeData(Data data) {...}

SERIALIZABLE Isolation

  • 이는 가장 엄격한 isolation level이다.
  • 동시성에 관련된 사이드 이펙트는 없다. 그러나 성능이 매우 떨어지게 된다. 왜냐하면 동시에 들어온 트랜잭션은 모두 serialize되어 순차적으로 수행되어야 하기 때문이다.
@Transactional(isolation = Isolation.SERIALIZABLE)
public void writeData(Data data) {...}

WrapUp

  • propagation 은 로직 처리를 수행할때 트랜잭션이 어떻게 수행되어야할지에 대한 설정이다. 이 설정을 통해서 트랜잭션을 필요에 따라 구분되어 사용할 수 있게 된다.
  • isolation level은 DBMS 데이터에 대해서 동시성 처리가 일어날때 어떠한 전략을 사용할지 레벨을 설정하는 것이며, 다른 트랜잭션 하에서 데이터를 읽을때 어떻게 데이터가 보이는지에 대한 설정이다.
  • 위와 같이 두 옵션을 적절히 이용하여 트랜잭션을 사용할 필요가 있다.

'JPA' 카테고리의 다른 글

[JPA] JPA 기초 11 Derived Query  (0) 2022.04.12
[JPA] JPA 기초 10 Entity Lifecycle  (0) 2022.04.12
[JPA] JPA 기초 09 Entity Event Hooking  (0) 2022.04.12
[JPA] JPA 기초 08 ManyToMany with Entity  (0) 2022.04.12
[JPA] JPA 기초 07 ManyToMany  (0) 2022.04.12
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/04   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30
글 보관함