Transaction
데이터베이스 관리 시스템 또는 유사한 시스템에서 상호작용의 단위이다.
여기서 유사한 시스템이란 트랜잭션이 성공과 실패가 분명하고 상호 독립적이며, 일관되고 믿을 수 있는 시스템을 의미
데이터의 정합성을 보장하기 위해 고안된 방법
Transaction 특징
- 원자성(Atomicity)
- 한 트랜잭션 내에서 실행한 작업들은 하나로 간주한다. 즉, 모두 성공 또는 모두 실패
- 일관성(Consistency)
- 트랜잭션은 일관성 있는 데이터베이스 상태를 유지한다. (data integrity 만족 등.)
- 격리성(Isolation)
- 동시에 실행되는 트랜잭션들이 서로 영향을 미치지 않도록 격리해야 한다.
- 지속성(Durability)
- 트랜잭션을 성공적으로 마치면 결과가 항상 저장되어야 한다.
Spring에서 트랜잭션 처리 방법
스프링에서는 트랜잭션 처리를 지원하는데 그 중 어노테이션 방식으로 @Transactional을 선언하여 사용하는 방법이 일반적이며, 선언적 트랜잭션이라 부른다.
클래스, 메서드위에 @Transactional이 추가되면, 이 클래스에 트랜잭션 기능이 적용된 프록시 객체가 생성된다.
이 프록시 객체는 @Transactional이 포함된 메소드가 호출 될 경우, PlatformTranactionManager를 사용하여 트랜잭션을 시작하고, 정상 여부에 따라 Commit 또는 Rollback 한다.
다 수 트랜잭션이 경쟁시 발생할 수 있는 문제
Dirty Read
트랜잭션 A가 어떤 값 1에서 2로 변경하고 아직 커밋하지 않은 상황에서 트랜잭션 B가 같은 값을 읽는 경우 트랜잭션 B는 2가 조회 된다.
트랜잭션 B가 2를 조회 한 후 혹시 A가 롤백되면 결국 트랜잭션 B는 잘못된 값을 읽게 된 것이다. 즉, 아직 트랜잭션이 완료되지 않은 상황에서 데이터에 접근을 허용할 경우 발생할 수 있는 데이터 불일치이다.
Non-Repeatable Read
트랜잭션 A가 어떤 값 1을 읽었따. 이후 A는 같은 쿼리를 또 실행할 예정인데, 그 사이에 트랜잭션 B가 값 1을 2로 바꾸고 커밋해 버리면 A가 같은 쿼리를 두번 날리는 사이 두 쿼리의 결과가 다르게 되어 버린다.
즉, 한 트랜잭션에서 같은 쿼리를 두 번 실행했을 때 발생할 수 있는 데이터 불일치이다.
(Dirty Read에 배해서는 발생할 확률이 적다)
Phantom Read
트랜잭션 A가 어떤 조건을 사용하여 특정 범위의 값들 [0,1,2,3,4] 읽었다.
이후 A는 같은 쿼리를 실행할 예정인데, 그 사이에 트랜잭션 B가 같은 테이블에 값 [5,6,7]을 추가해 버리면 A가 같은 쿼리 두 번을 날리는 사이 두 쿼리의 결과가 다르게 되어 버린다.
즉, 한 트랜잭션에서 일정 범위의 레코드를 두 번 이상 읽을 때 발생하는 데이터 불일치이다.
Spring Transactional
Isolation(격리 수준)
트랜잭션에서 일관성이 없는 데이터를 허용하도록 하는 수준
- Default
- 기본 격리 수준(기본설정, DB의 Isolation Level을 따름)
- READ_UNCOMMITED(level 0)
- 커밋되지 않는 (트랜잭션 처리중인) 데이터에 대한 읽기를 허용
- 즉 어떤 사용자가 A라는 데이터를 B라는 데이터로 변경하는 동안 다른 사용자는 B라는 아직 완료되지 않은 (Uncommitted 혹은 Dirty) 데이터 B를 읽을 수 있다.
- READ_COMMITED(level 1)
- 트랜잭션이 커밋 된 확정 데이터만 읽기 허용
- 어떠한 사용자가 A라는 데이터를 B라는 데이터로 변경하는 동안 다른 사용자는 해당 데이터에 접근할 수 없다.
- Dirty Read 방지
- REPEATABLE_READ(level 2)
- 트랜잭션이 완료될 떄까지 SELECT 문장이 사용하는 모든 데이터에 Shared Lock이 걸리므로 다른 사용자는 그 영역에 해당되는 데이터에 대한 수정이 불가능하다.
- 선행 트랜잭션이 읽은 데이터는 트랜잭션이 종료될 때까지 후행 트랜잭션이 갱신하거나 삭제가 불가능 하기 떄문에 같은 데이터를 두 번 쿼리했을 때 일관성 있는 결과를 리턴한다.
- Non-Repeatable Read 방지
- SERIALIZABLE(level 3)
- 데이터의 일관성 및 동시성을 위해 MVCC(Multi Version Concurrency Control)을 사용하지 않음
- 트랜잭션이 완료될 때까지 SELECT 문장이 사용하는 모든 데이터에 Shared lock이 걸리므로 다른 사용자는 그 영역에 해당되는 데이터에 대한 수정 및 입력이 불가능하다.
- Phantom Read 방지
참고MVCC
MVCC는 다중 사용자 데이터베이스 성능을 위한 기술로 데이터 조회 시 LOCK을 사용하지 않고 데이터의 버전을 관리해 데이터의 일관성 및 동시성을 높이는 기술
Propagation (전파 옵션)
트랜잭션 동작 도중 다른 트랜잭션을 호출(실행)하는 상황에 선택할 수 있는 옵션
- REQUIRED
- 디폴트 속성, 부모 트랜잭션 내에서 실행하며 부모 트랜잭션이 없는 경우 새로운 트랜잭션을 생성한다.
- SUPPORTS
- 이미 시작된 트랜잭션이 있으면 참여하고 그렇지 않으면 트랜잭션 없이 진행하게 만든다.
- REQUIRES_NEW
- 부모 트랜잭션을 무시하고 무조건 새로운 트랜잭션이 생성
- MANDATORY
- REQUIRED와 비슷하게 이미 시작된 트랜잭션이 있으면 참여한다.
- 반면 트랜잭션이 시작된 것이 없으면 새로 시작하는 대신 예외를 발생
- NOT_SUPPORTED
- 트랜잭션을 사용하지 않게 한다.
- 이미 진행 중인 트랜잭션이 있으면 보류시킨다.
- NEVER
- 트랜잭션을 사용하지 않도록 강제한다.
- NESTED
- 이미 진행중인 트랜잭션이 있으면 중첩 트랜잭션을 시작
- 중첩 트랜잭션은 트랜잭션 안에 다시 트랜잭션을 만드는 것이다.
중첩된 트랜잭션은 먼저 시작된 부모 트랜잭션의 커밋과 롤백에는 영향을 받지만 자신의 커밋과 롤백은 부모 트랜잭션에게 영향을 주지 않는다.
Read Only
- 트랜잭션을 읽기 전용으로 설정할 수 있다.
- 성능을 최적화하기 위해 사용할 수 도있 있고 특정 트랜잭션 작업 안에서 쓰기 작업이 일어나는 것을 의도적으로 방지하기 위해 사용 할 수도 있다.
- 일반적으로 읽기 전용 트랜잭션이 시작된 이후 INSERT, UPDATE, DELETE 같은 쓰기 작업이 진행되면 예외 발생
트랜잭션 롤백 예외
RollbackFor
특정 예외가 발생시 강제로 Rollback
@Transactional(rollbackFor=Exception.class)
noRollbackFor
특정 예외의 발생 시 Rollback 처리되지 않음
@Transactional(noRollbackFor=Exception.class)
TimeOut 속성
지정한 시간 내에 해당 메소드 수행이 완료되지 않는 경우 rollback 수행
긴 글 읽어 주셔서 감사합니다.
'JAVA & KOTLIN' 카테고리의 다른 글
[JAVA] UUID Version 7은 어떻게 사용할까? (0) | 2024.12.30 |
---|---|
[JAVA] Java Instant 주요 메소드 (0) | 2024.12.24 |
[KOTLIN] Kotlin에서 Value Object 언제 사용할까? (2) | 2024.12.21 |
[JAVA] java 1.8에서 변경 된 time (0) | 2024.12.17 |
[KOTLIN] Kotlin by 키워드: 상속보다 위임을 선택해야 하는 이유 (0) | 2024.12.16 |