스프링 프레임워크를 사용한다면 @Transactional 을 Service단에 붙여서 자주 사용할 것이다.
이 경우 아래와 같이 isolation (격리수준)이 default(기본값)으로 지정된다.
@Transactional의 옵션인 isolation의 기본값은 Isolation.DEFAULT 라고 한다.
그렇다면 Isolation.DEFAULT란 무엇일까?
우선 Isolation은 TransactionDefinition 인터페이스에 해당하는 Transactional 어노테이션과 함께 사용할 트랜잭션 격리 수준(transaction isolation levels)을 나타내는 열거형(Enumeration)이다.
열거형 값은 다음 5가지가 있다.
- DEFAULT
- READ_UNCOMMITTED
- READ_COMMITTED
- REPEATABLE_READ
- SERIALIZABLE
이건 DB 트랜잭션 격리수준을 의미하는 것으로 조금 이따 살펴보도록 하고,
DEFAULT에 뭐라고 적혀있는지 살펴보자.
Use the default isolation level of the underlying datastore.
기본 데이터 저장소의 기본 격리 수준을 사용한다.
All other levels correspond to the JDBC isolation levels.
다른 모든 수준은 JDBC 격리 수준에 해당한다.
즉, 내가 사용하는 DB의 기본 격리 수준을 따르는 것이기 때문에 각 DB의 기본 격리 수준을 알아보자
🚀 MySQL default isolation level (기본 격리 수준)
MySQL 8.0 버전(최신버전)에 따르면 기본 격리 수준은 Inno DB의 REPEATABLE_READ 라고 한다.
MySQL 5.6, 5.7 버전도 똑같이 REPEATABLE_READ라고 한다.
🚀 Oracle default isolation level
Oracle DB 21c(최신버전)은 READ_COMMITTED가 기본 격리 수준이라고 한다.
Oracle DB 19c, 12c 또한 공식 문서를 확인해본 결과 마찬가지이다.
🚀 PostgreSQL default isolation level
PostgreSQL 15(최신버전)은 READ_COMMITTED가 기본 격리 수준이다.
PostgreSQL 14, 13, 12, 11 버전 또한 마찬가지이다.
🚀 MongoDB default isolation level
MongoDB 6(최신버전)은 READ_UNCOMMITTED가 기본 격리 수준이다.
MongoDB 5, 4.4, 4.2 또한 마찬가지이다.
🚀 Microsoft SQL Server default isolation level
Microsoft SQL Server 2022 (최신버전)은 READ_COMMITTED가 기본 격리 수준이다.
Microsoft SQL Server 2019, 2017, 2016 버전 또한 마찬가지이다.
🚀 각 DB들의 기본 격리 수준(isolation level)
- 왼쪽으로 갈수록 동시성은 강하지만, 격리성은 약함
- 오른쪽으로 갈수록 동시성은 약해지고, 격리성은 강함
격리성(isolation) : 트랜잭션 수행 시 서로 끼어들지 못하는 것을 의미함
MySQL, Oracle, PostgreSQL, Microsoft SQL Server는 RDBMS로써 어느정도 격리성은 지키고 있다.
하지만 NoSQL인 MongoDB는 가장 낮은 격리 수준을 보이지만 동시성이 가장 높다는 차이점이 보인다.
자 그럼 각 격리 수준들의 특징을 살펴보자
🚀 isolation level (격리 수준)
- 위로 갈수록 동시성이 강해지지만 격리성은 약해짐
- 밑으로 갈수록 동시성이 약해지지만 격리성은 강해짐
- 각 격리수준마다 더티 리드, 반복 가능하지 않은 조회, 팬텀 리드가 발생할 수 있음
😈 PHANTOM READ(팬텀 리드)
- 한 트랜잭션 내에서 동일한 쿼리를 보냈을 때 해당 조회 결과가 다른 경우
- e.g. 회원A가 레코드를 여러번 조회하는데, 중간에 회원B가 레코드를 추가하여서 회원A가 다시 조회 시 존재하지 않은 레코드를 조회하게 되는 경우
- 즉, 동일한 조회 쿼리를 보냈지만 처음과 다르게 없던 데이터가 보이거나 있었던 데이터가 사라지는 것을 의미함
- 이를 방지하려면 쓰기 방지(Write Lock, Exclusive Lock)를 걸어야 함
😈 NON REPEATABLE READ(반복 가능하지 않은 조회)
- 한 트랜잭션 내의 같은 행에 두 번 이상 조회가 발생했는데 그 값이 다른 경우
- e.g. 회원A가 레코드를 여러 번 조회하던 중 회원B가 레코드를 변경하여 회원A가 조회한 값이 달라지는 경우
팬텀리드와 반복 가능하지 않은 조회 둘 다 한 트랜잭션 내에서 조회 쿼리를 여러번 실행했을 때 결과가 다른 것이다. 여기서 차이점은 반복 가능하지 않은 조회는 조회된 행 값이 다른 경우이고, 팬텀 리드는 없던 행이 생기거나 행이 사라져서 다른 행이 선택될 수 있는 경우
😈 DIRTY READ(더티 리드)
- 한 트랜잭션이 실행 중일 때 다른 트랜잭션에 의해 수정되었지만 아직 '커밋되지 않은' 행의 데이터를 읽을 수 있을 때 발생함
- 반복 가능하지 않은 조회와 유사함
- e.g. 회원A가 행의 값을 변경하고 커밋하지 않은 상태인데, 회원B가 해당 행의 변경된 값을 조회하는 경우
자 격리 수준에 따른 현상을 살펴보았으니 이제 각 격리 수준의 특징을 알아보자.
🚀 READ UNCOMMITTED
- 가장 낮은 격리 수준
- 하나의 트랜잭션이 커밋되기 전에 다른 트랜잭션에 노출되는 문제가 있지만 가장 빠름
- 데이터 무결성을 위해 되도록 사용하지 않는 것이 좋음
- 조금의 행이 제대로 조회되지 않더라도 괜찮은 거대한 양의 데이터를 어림잡아 집계하는 데는 좋음
🚀 READ COMMITTED
- 가장 많이 사용되는 격리 수준
- Oracle, PostgreSQL, Microsoft SQL Server에서 기본 격리 수준
- READ UNCOMMITTED와 달리 다른 트랜잭션이 커밋하지 않은 정보는 읽을 수 없음
- 즉, 커밋 완료된 데이터에 대해서만 조회 허용
- 하지만 어떤 트랜잭션이 접근한 행을 다른 트랜잭션이 수정할 수 있음
- e.g. 트랜잭션A가 수정한 행을 트랜잭션B가 수정할 수 있음
- 따라서 트랜잭션A가 수정한 행을 다시 읽을 때 트랜잭션B가 수정한 값으로 덮어져서 다른 내용이 발견될 수 있음
🚀 REPEATABLE READ
- MySQL의 기본 격리 수준
- 하나의 트랜잭션이 수정한 행을 다른 트랜잭션이 수정할 수 없도록 막아주지만, 새로운 행을 추가하는 것은 막지 않음
- 팬텀리드 O, 반복 가능하지 않은 조회 X
🚀 SERIALIZABLE
- 트랜잭션을 순차적으로 진행시킴
- 여러 트랜잭션이 동시에 같은 행에 접근 X
- 매우 엄격한 수준으로 해당 행에 대해 격리시키고 이후 트랜잭션이 이 행에 대해 발생한다면 기다려야 함
- 교착 상태가 일어날 확률이 많고, 가장 성능이 떨어지는 격리 수준
'Spring > Spring' 카테고리의 다른 글
SpringBoot 랜덤포트로 실행하기 (3) | 2023.05.15 |
---|---|
선착순 쿠폰 발급을 위한 redis 분산락 (0) | 2023.05.11 |
포스트맨으로 url 요청했는데 405 에러 (0) | 2023.02.13 |
스프링 부트 의존관계 주입 에러 (0) | 2023.02.13 |
스프링부트 - 하루에 한 번 쿠키 기반 조회수 증가 구현 (1) | 2022.10.03 |