[CS 퀴즈] 오답노트 (8)
CS 퀴즈 (8)
트랜잭션이란 (Transaction)
데이터베이스의 상태를 변화시키기 위해 수행하는 작업단위
- 원자성(Atomicity)
- 절반만 되고 그런거 없음
- All or Nothing, 모든 작업이 실행되거나 혹은 모두 실행되지 않아야 한다.
- A 계좌에서 B 계좌로 전액을 송금할 때
- A 계좌 잔액 줄리기 작업과 B 계좌 잔액 늘리기 작업은 함께 성공하거나 함께 실패해야 한다.
- 일관성(Consistency)
- 작업처리 결과는 항상 일관적이여야한다.
- 작업처리 결과는 항상 일관성이 있어야한다.
- 과거에 어떤 작업을 했을 때 A라는 결과가 나왔다면
- 그 다음에 동일한 작업을 할 때에 무조건 A가 나와야 한다.
- 모든 트랜잭션이 종료된 후에는 DB의 제약 조건을 모두 지키고 있는 상태가 되어야 한다.
- 잔액은 0원 이상이다. -> 이를 위반하는 트랜잭션은 모두 중단된다.
- 독립성(Isolation)
- 여러 개의 트랜잭션이 이루어질 때 각 트랜잭션은 독립적으로 한 개씩 수행되어야 한다.
- A 트랜잭션이 하는 일을 B 트랜잭션은 모들게 해야한다.
- 성능 관계에 있어서 READ_UNCOMMITTED > READ_COMMITTED > REPEATABLE_READ > SERIALIZABLE 순서로 성능은 떨어지고 격리성은 증가한다.
- 격리성이 낮을 때는 Drity read, Phantom read 등이 발생한 다.
- 일반적으로 MYSQL InnoDB의 기본 값인 REPEATBLE_READ 를 많이 활용한다.
- 지속성(Durability)
- 트렌젝션이 성공했을 경우 그 결과 값은 영구적으로 지속되어야 한다.
- commit을 하게 되면 지속(저장)이 꼭 된다.
- DB 저장이 실패하더라도 모든 로그를 모두 남겨서 DB에 순차적으로 모두 반영되도록 한다.
주로 DB에 문제가 생겼을 때 롤백 시키기 위해 사용된다.
- 트랜잭션 연산 - 원자성 문제
- 커밋(Commit) - 트랜잭션이 전체가 성공적으로 이루어졌을 때 마무리 작업으로 커밋 -> 모든 수정사항 반영
- 롤백(Rollback) - 트랜잭션이 이루어질 때 어떠한 예외상황이 발생 했을 시 전체를 처음으로 되돌림
- 예를 들어 5단계가 있을 때 중간에 4개가 성공해도 1개가 실패한다면 전부 취소시킴
여러 트랜잭션이 경쟁하면 생기는 문제
Dirty Read
- 트랜잭션 A : 테이블의 3번째 row 수정중 (커밋전)
- 트랜잭션 B : 테이블의 3번째 row 조회시도
3번째 row가 2로 수정중이였는데 이 때 B가 조회하면 2로 데이터를 읽어감 하지만 이 때 트랜잭션 실패로 롤백이 되서 기존 데이터가 1로 다시 바뀐다면 B는 잘못된 값을 읽어가게됨(접근이 가능했기 때문에 문제가됨 -> 읽지 못 하게 보호해야함)
Non-Repeatable Read -일관성 문제
- 트랜잭션 A : 테이블 3번째 row 조회 x 2
- 트랜잭션 B : 테이블 3번째 row 수정 후 커밋
A가 조회했을 때 아직 트랜잭션이 끝나지 않았지만 B가 껴들어서 수정후 커밋해버리면 A가 첫 번째 조회했을 때와 두 번째 조회했을 때의 값이 달라짐
Phantom Read
- 트랜잭션 A : 테이블 0~4번째 row 조회 x 2
- 트랜잭션 B : 테이블 3번째 row 수정 후 커밋
Non-Repeatable Read 은 특정 값을 두 트랜잭션이 경쟁했을 때 생기는 문제
Phantom Read 는 특정 범위 내에서 값을 경쟁했을 때 생기는 문제
Spring 에서 트랜잭션을 어떻게 적용할까?
@Transactional
가장 간단하고 널리 사용함 -> 선언적 트랜잭션
클래스나 매서드 위에 달림 -> 프록시 객체가 생김
(PlatformTransaction Manager) -> 트랜잭션을 관리해줌
Spring 트랜잭션의 세부 설정들
- Isolation (격리수준)
- Propagation (전파수준)
- ReadOnly 속성
- 트랜잭션 롤백 예외
- timeout 속성
Isolation (격리수준)
@Transactional(isolation = Isolation.Default)
트랜잭션에서 일관성이 없는 데이터를 허용하는 수준
- DEFAULT
- READ_UNCOMMITTED (Dirty Read 발생) (헐겁)
- READ_COMMITTED (Dirty Read 방지) (트랜잭션 와중에는 아무도 못 읽음 커밋이 되야만 접근 가능)
- REPEATABLE_READ (Non-Repeatable Read 방지) (보통 무난하게 많이 씀) (트랜잭션 전체가 완료될 때까지 셀렉트 된 부분에 락을 걸어서 격리 -> 다른 사용자는 조회,접근 조차 안됨)
- SERIALIZABLE (Phantom Read 방지) (일관성 빡빡) -> 성능저하 발생
Propagation (전파수준)
트랜잭션 동작 도중 다른 트랜잭션을 호출하는 상황
트랜잭션을 시작하거나 기존 트랜잭션에 참여하는 방법에 대해 결정하는 속성 값
- REQUIRED -> 디폴트
- 부모트랜잭션 A, 자식트랜잭션 B -> A가 B를 호출 했을 떄 부모 트랜잭션안에서 함수 B도 함께 진행
- 만약 A는 트랜잭션이 없고 B만 있을 경우 B를 위한 새로운 트랜잭션을 만든다.
- SUPPORTS -> 이미 시작한 트랜잭션이 있으면 참여하고 없으면 트랜잭션 없이 진행
- REQUIRES_NEW -> 부모A 자식B 이렇게 둘 다 트랜잭션이 있을 경우 부모A 트랜잭션따로 자식 B따로 트랜잭션을 만들어 동작한다..
- NESTED -> 이미 트랜잭션이 있는 경우에 중첩해서 진행 -> 트랜잭션 안에서 새로운 트랜잭션이 진행
- -> 부모트랜잭션이 커밋되는지에 대해서 영향을 받지만 자식 트랜잭션의 롤백여부는 부모트랜잭션에 영향을 미치지 않음
- 부모가 롤백이되면 자식도 롤백 하지만 부모는 롤백되지 않은 상태에서 자식이 롤백될 경우 부모는 커밋되고 자식은 그대로 롤백이됨
- 예를 들어 로그작성과 일기작성이 이루어질 때 로그작성이 실패하더라도 데이터 작성은 진행되어야 하는 경우 -> 반대로 데이터를 작성이 실패했을 경우 로그도 롤백 되어야함
- ….. 그 외 더 있음…
ReadOnly 속성
트랜잭션을 읽기 전용 속성으로 지정
@Transactional(readOnly = true)
트랜잭션 성능 최적화 및 특정 트랜잭션안에서 의도적으로 사용 가능
트랜잭션 롤백 예외
예외 발생시 트랜잭션 롤백시킬 경우를 설정
Transactional(rollbackFor = Exception.class)
Transactional(noRollbackFor = Exception.class)
Default : RuntimeException, Error 특정 예외에는 롤백 시키고 싶지 않을 경우 사용
timeout 속성
일정 시간 내에 트랜잭션을 끝내지 못 할 경우 롤백
@Transactional(timeout=10)
데이터베이스에 문제가 생겨 오래 걸릴 경우
댓글남기기