6.1 트랜잭션(Transaction)이란?
Transaction(트랜잭션)
- 데이터베이스의 상태를 변화시키기 위해 수행하는 작업 단위를 '트랜잭션'이라고 한다.
- ex) 오늘의 날씨 데이터를 가져와서 일기 정보를 DB에 저장하기까지의 작업 단위를 트랜잭션이라고 볼 수 있다.
- 트랜잭션의 속성
- 원자성(Atomicity) - 트랜잭션이 데이터베이스에 모두 반영되거나 또는 반영되지 않거나 반드시 둘 중 하나여야만 하다.
- 일관성(Consistency) - 트랜잭션의 작업 처리 결과는 언제나 일관적이어야한다.
- 독립성(Isolation) - 여러 트랜잭션들이 독립적으로 수행되어야 한다.
- 지속성(Durablity) - 트랜잭션이 성공적으로 완료된 경우 변화된 상태가 지속적으로 반영되어야한다.
- 트랜잭션의 연산 - 원자성 만족시키기 위한 방법
- 커밋(Commit) - 트랜잭션이 성공적으로 끝났을 때, 모든 수정 사항을 반영하기 위해 커밋한다.
- 롤백(Rollback) - 어떤 예외 사항이나 문제가 발생하는 경우에 롤백한다. 트랜잭션 작업 하기 전의 데이터베이스 상태로 돌아간다.
여러 트랜잭션이 경쟁하면 생기는 문제는? (면접 빈출)
- Dirty Read: 트랜잭션A는 다이어리 테이블의 세 번째 row를 수정하고 있다. 트랜잭션B는 다이어리 테이블의 세 번째 row를 조회하려고 하는 경우
- Non-Repeatable Read(일관성을 헤치는 경우): 트랜잭션A (세 번째 row를 조회하는 중) vs 트랜잭션B(세 번째 row 수정 후 커밋)
- Phantom Read: 트랜잭션A (첫 번째 ~ 네 번째 row를 조회하는 중) vs 트랜잭션B(세 번째 row 수정 후 커밋)
- 2) 3) 의 차이는? 2: 특정 값에 대해 경쟁했을 때 문제, 3: 특정 범위 내에서 경쟁했을 때 문제
6.2 스프링에서의 트랜잭션(Transaction)
스프링 트랜잭션 세부 설정
- @Transaction(선언적 트랜잭션) - 클래스나 메서드 위에 어노테이션을 추가한다.
- @Transaction이 붙은 클래스나 메서드에 대해 트랜잭션 기능이 적용된 프록시 객체를 생성한다.
- PlatformTransactionManager가 트랜잭션을 시작하고 관리한다. 트랜잭션에 성공했는지 아닌지 판단해서 커밋 또는 롤백하도록 한다.
cf) 프록시 서버(proxy server): 클라이안트가 자신을 통해 다른 네트워크 서비스에 간접적으로 접속할 수 있게 해주는 컴퓨터 시스템이나 응용프로그램을 가리킨다.
- 서버와 클라이언트 사이에서 중계기로서 대리로 통신을 수행하는 것을 가리켜 '프록시', 중계 기능을 하는 것은 프록시 서버라고 부른다.
- 1. Isoaltion(격리 수준) - 중요!
- Isoaltion이란 트랜잭션에서 일관성이 없는 데이터를 허용하는 수준을 말한다.
- Ex) @Transaction(isolation=Isolation.DEFAULT)
- DEFAULT: 가장 기본적으로 쓰인다. (금융업이나 정확성이 중요한 경우에는 특정 트랜잭션에 대해서 DEFAULT 가 아닌 REPEATABLE_READ이나 SERIALIZABLE로 설정한다.)
- READ_UNCOMMITTED: 커밋 전 이더라도 read 가능 - Dirty Read 발생 가능
- READ_COMMITTED: 커밋 후에야 read 가능 - Dirty Read 방지
- REPEATABLE_READ: 트랜잭션 전체가 완료될 때까지 SELECT문이 사용한 부분에 대해 shared lock을 건다. 앞서 어떤 트랜잭션이 read중이면 트랜잭션이 종료되기 전까지 다른 트랜잭션이 와서 같은 데이터를 처리할 수 없다. - Non-Repeatable Read & Dirty Read 방지
- SERIALIZABLE: 트랜잭션이 완료될 때까지 사용중인 모든 데이터에 대해 shared lock을 건다. - Phantom Read 방지, 일관성 & 동시성 유지, (가장 빡빡한 조건)
- 2.Propagation(전파 수준)
- 트랜잭션 동작 도중에 다른 트랜잭션을 호출하는 상황을 말한다.
- 트랜잭션을 시작하거나 기존 트랜잭션에 참여하는 방법에 대해 결정하는 속성값이다.
- Ex)
- REQUIRED: (디폴트) 부모 트랜잭션 안에서 자식 트랜잭션까지 함께 실행된다. 부모 트랜잭션이 없는 경우에만 새로운 트랜잭션을 실행한다.
- SUPPORT: 이미 시작된 트랜잭션이 있으면 참여하고 없으면 트랜잭션 없이 진행한다.
- REQUIRES_NEW: 부모 트랜잭션 안에서 함수가 실행되는 경우이더라도 자식을 위한 새로운 트랜잭션을 만들어서 동작한다.
- NESTED: 이미 시작된 트랜잭션이 있는 경우에 중첩해서 트랜잭션을 하나 더 만들어서 실행하는 경우이다. 중첩된 트랜잭션은 부모 트랜잭션이 커밋 / 롤백이 됐는지 영향 받지만, 반면에 중첩된 트랜잭션의 커밋 / 롤백 여부는 부모 트랜잭션에 영향을 주지 않는다.
- NESTED의 ex) 일기 작성 관련해서 로그를 DB에 저장하는 상황
- 로그 저장 실패하는 경우 일기 작성까지 롤백되면 안된다.
- 일기 작성이 실패한다면 로그 작성까지 롤백되어야한다.
- NESTED의 ex) 일기 작성 관련해서 로그를 DB에 저장하는 상황
- 3. readOnly 속성
- 트랜잭션을 읽기 전용 속성으로 지정한다.
- @Transactional(readOnly = true)
- false가 기본값이다.
- readOnly를 이용하면 트랜잭션의 성능이 빨라진다. 조회만 하는 경우는 웬만하면 붙여서 성능을 높이도록 한다.
- 4. 트랜잭션 롤백 예외
- 예외 발생했을 때, 트랜잭션 롤백시킬 경우를 설정한다.
- Ex)
- @Transactional(rollbackFor= Exception.class): 어떤 예외가 발생하면 롤백된다.
- @Transactional(noRollbackFor= Exception.class): 어떤 예외가 발생해도 롤백 되지 않고 커밋된다.
- 예외 발생했을 때, 트랜잭션 롤백시킬 경우를 설정한다.
- 5. Timeout 속성
- 일정 시간 내에 트랜잭션을 끝내지 못하면 롤백한다.
- 격리 수준이 빡빡한 경우 속도가 느리면 timeout 속성도 함께 쓰면 좋다.
6.3 트랜잭션(Transaction)이란?
트랜잭션을 코드에 반영하기
- Service에 트랜잭션을 많이 붙인다.
- WeatherApplication위에 @EnableTransactionManagement을 붙이면 프로젝트 안에서 트랜잭션이 활성화된다.
- Service에도 @Transactional(readOnly = true)을 붙인다. 그럼 Service 각 메서드가 트랜잭션으로 동작한다.
@Transactional(readOnly = true)
Ex) 클래스와 메서드에 readOnly가 다르게 붙으면?
- 지금 Service클래스에 트랜잭션 애너테이션 readOnly = true가 붙은 상태에서 Service의 하위 메서드 createDiary()에 다음과 같이 어노테이션을 붙인다.
@Transactional(readOnly = false)
http://localhost:8080/create/diary?date=2022-08-01
- 일기 내용(I want to learn spring boot! AM 12:35)을 적고 위 링크를 이용해서 POST 한 다음,
http://localhost:8080/read/diary?date=2022-08-01
- GET
Note) 실행 결과
- 아래 다이어리에 새로운 text가 나온다.
- 데이터베이스에 값이 잘 들어가고 아래의 쿼리문이 실행된 걸 알 수 있다.
cf)
- readOnly = false가 기본값이라서 다음과 같은 알림을 볼 수 있다.
Ex) 트랜잭션 예시
- createDiary() - 격리 수준 지정 (가장 빡빡한 serializable)
<hide/>
@Transactional(isolation = Isolation.SERIALIZABLE)
public List<Diary> readDiary(LocalDate date){
}
- test 코드에 @Transactional을 붙이면 변경 사항을 커밋하지 않는다. 모두 롤백 처리해버린다.
- test 코드 안에 데이터베이스 변경 내용이 있더라도 실제 데이터베이스에 영향을 주지 않도록 한다.
<hide/>
@SpringBootTest
@Transactional
class JpaMemoRepositoryTest {
...
}
출처 - 제로베이스 백엔드 스쿨 (김조현 강사님)
'Spring Projcect > 날씨 일기 프로젝트' 카테고리의 다른 글
Chapter 08. 로그(log) 남기기 (0) | 2022.09.01 |
---|---|
Chapter 07. 날씨 저장 스케쥴링 (0) | 2022.09.01 |
Chapter 05. 날씨 데이터 CRUD (0) | 2022.08.31 |
Chapter 04. 날씨 데이터 저장하기 (0) | 2022.08.31 |
Chapter 03. DB에 작업하기 (0) | 2022.08.30 |