728x90
테스트 케이스에서의 @Transactional
@Transactional ?
- Spring의 JPA에서 많이 사용되는 기술로, 선언적 트랜잭션이라 부른다
- 트랜잭션을 시작하고
Commit
을 시켜주고, Exception 발생 시Rollback
을 시켜준다.
- 이를 위해 Transaction 어노테이션이 실행되기 전에 transaction begin 코드를 삽입하여 메서드가 실행 된 후 transaction commit 코드를 삽입하여 객체 변경 감지를 수행하게 유도한다.
다수의 트랜잭션에서 발생할 수 있는 문제
Dirty Read
- A 트랜잭션이 어떤 값을 1에서 2로 변경하고 아직 커밋하지 않은 상태에서 B 트랜잭션이 그 값을 읽는 경우 2가 조회된다.
- 트랜잭션 B가 2를 조회 한 후 A가
Rollback
된다면 B 트랜잭션는 잘못된 값을 읽게 되는 것이다.
- 즉, 아직 트랜잭션이 완료되지 않는 상황에서 데이터에 접근이 허용할 경우 발생할 수 있는 데이터 불일치이다.
Non-Repeatable Read
- A 트랜잭션이 어떤 값 1을 읽고 같은 쿼리를 실행할 예정인데, 그 사이에 B 트랜잭션이 1을 2로 변경하고 커밋한다.
- 그러면 A는 같은 쿼리를 두 번 날리는 사이 두 쿼리의 결과가 다르게 된다.
- 즉, 한 트랜잭션에서 같은 쿼리를 두번 실행했을 때 발생할 수 있는 데이터 불일치이다.
Phantom Read
- A 트랜잭션이 어떤 조건을 사용하여 특정 범위의 값들 [0,1,2,3,4]를 읽었다.
- 이 후 A는 같은 쿼리를 실행할 예정인데, 그사이에 트랜잭션 B가 같은 테이블에 값[5,6,7]을 추가하면 A는 같은 쿼리를 두 번 날리는 사이 두 쿼리의 결과가 달라진다.
- 즉, 한 트랜잭션에서 일정 범위의 레코드를 두 번 이상 읽을 때 발생하는 불일치이다.
스프링 트랜잭션의 속성
격리수준 (isolation)
- 트랜잭션에서 일관성이 없는 데이터를 허용하도록 하는 수준
- Default
- 기본 격리 수준
- READ_UNCOMMITED ( level 0 )
- 커밋되지 않은 데이터에 대한 읽기 허용
- Dirty Read 발생
- READ_COMMITED ( level 1 )
- 커밋이 완료된 확정 데이터만 읽기 허용
- Dirty Read 방지
- REPEATABLE_READ ( level 2 )
- 트랜잭션이 완료될 때까지 SELECT 문장이 사용하는 모든 데이터에 shared lock이 걸려서 다른 사용자는 그 영역에 해당하는 데이터를 수정을 할 수 없다.
- 선행 트랜잭션이 읽을 경우 그 트랜잭션이 종료될 때까지 갱신하거나 삭제가 불가능하여 같은 데이터를 두 번 쿼리했을 때 일관성 있는 결과를 리턴한다.
- Non-Repeatable Read 방지
- SERIALIZABLE ( level 3 )
- 데이터의 일관성 및 동시성을 위해 MVCC를 사용하지 않는다.
- MVCC ( Multi Version Concurrency Control ) - 다중 사용자 데이터베이스 성능을 위한 기술로 데이터 조회 시 LOCK을 사용하지 않고 데이터의 버전을 관리하여 데이터의 일관성 및 동시성을 높이는 기술
- 트랜잭션이 완료될 때까지 SELECT 문장이 사용하는 모든 데이터에 shared lock이 걸려서 다른 사용자는 그 영역에 해당하는 데이터를 수정을 할 수 없다.
- Phantom Read 방지
- 데이터의 일관성 및 동시성을 위해 MVCC를 사용하지 않는다.
- 단, 격리 수준이 올라갈 수롣 성능이 저하 될 수 있다.
readOnly
- 트랜잭션을 읽기 전용으로 설정한다.
- 성능을 최적화하거나 특정 트랜잭션 작업 안에서 쓰기 작업이 일어나는 것을 의도적으로 방지할 수 있다.
- 일부 트랜잭션 매니저의 경우 읽기전용 속성을 무시하고 쓰기 작업을 허용할 수 있으므로 주의해야한다.
- 일반적으로 읽기 전용 트랜잭션이 시작된 이후 INSERT, UPDATE, DELETE 같은 쓰기 작업이 진행되면 예외가 발생한다.
- 보통 get이나 find 같은 이름의 메소드를 모두 읽기전용으로 하면 편리하다.
- @Transactional 의 경우 각각의 메소드를 지정해줘야한다.
@Transactional(readOnly = true)
참조
https://goddaehee.tistory.com/167
https://me-analyzingdata.tistory.com/entry/SpringTransactional과-JUnit-Test
'SQL' 카테고리의 다른 글
MySQL Select 조회 성능을 위한 Index 적용기 (0) | 2022.08.04 |
---|---|
트랜잭션 (Transaction) (0) | 2022.04.20 |
[SQL] Index ( 인덱스 ) 의 구조와 동작 (0) | 2022.02.25 |
Uploaded by Notion2Tistory v1.1.0