티스토리 뷰
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 가 있다.
- propagation: 이는 세션의 트랜잭션을 어떻게 이용할지에 대한 설정이다.
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
링크
TAG
- mongo
- java
- deploy
- Database
- Gorilla
- AWS
- kubectl
- docker
- kubernetes
- argocd
- kafka-springboot
- gitops
- Spring
- docker-compose
- NodeSelector
- springboot
- Terraform
- D3
- CD
- Golang
- MySQL
- jpa
- tfsec
- declative
- CI
- mapping
- MongoDB
- Kafka
- go
- jenkins
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
글 보관함