[DB]트랜잭션 정리
- study
- 2021. 12. 2. 12:57
에이든의 트랜잭션 매커니즘, 샐리, 예지니어스의 트랜잭션 테코톡을 듣고 정리한 글 입니다.
트랜잭션
- 여러 쿼리를 논리적으로 하나의 작업으로 묶어주는 것
- 하나의 트랜잭션은 커밋 혹은 롤백된다.
- 데이터베이스에 저장된 데이터베이스의 무결성과 동시성의 성능을 지키기위해 트랜잭션의 설정이 중요
ACID
- 트랜잭션이 안전하게 수행된다는 것을 보장하기 위한 성질
- Atomicity
- 트랜잭션은 DB에 모두 반영되거나, 전혀 반영되지 않아야 한다.
- 완료되지 않은 트랜잭션의 중간 상태를 DB에 반영해서는 안 된다.
- Consistency
- 트랜잭션 작업처리결과는 항상 일관성 있어야 한다.
- 데이터베이스는 항상 일관된 상태로 유지되어야 한다.
- Isolation
- 둘 이상의 트랜잭션이 동시 실행되고 있을 때, 어떤 트랜잭션도 다른 트랜잭션 연산에 끼어들 수 없다.
- Durability
- 트랜잭션이 성공적으로 완료되었으면 결과는 영구히 반영되어야 한다.
- 커밋이 되었다면, 정전과 같이 예상치 못한 문제가 발생 되었더라도 데이터는 반영된 그대로 남아있어야 한다.
트랜잭션 격리 수준
- 동시에 DB 접근할 때 그 접근을 어떻게 제어할지에 대한 설정
- 격리 수준이 높아 질 수록 데이터 정합성은 좋아지나 동시성 성능이 떨어진다.
격리수준
- READ-UNCOMMITTED
- 커밋 전의 트랜잭션의 데이터 변경 내용을 다른 트랜잭션이 읽는 것을 허용
- READ-COMITTED
- 커밋이 완료된 데이터만 다른 트랜잭션에서 조회가능
- 트랜잭션이 이루어지는 동안 다른 사용자는 해당 데이터에 접근이 불가능하다.
- REPEATABLE-READ
- 트랜잭션 범위 내에서 조회한 내용이 항상 동일함을 보장
- SERIALIZABLE
- 한 트랜잭션에서 사용하는 데이터를 다른 트랜잭션에서 접근 불가
DIRTY READ | NON-REPEATABLE READ | PHANTOM READ | |
READ UNCOMMITTED | 발생 | 발생 | 발생 |
READ COMMITED | 없음 | 발생 | 발생 |
REPEATABLE READ | 발생 | 발생 | 발생 (InnoDB는 없음) |
SERIALIZABLE | 없음 | 없음 | 없음 |
- DIRTY READ
- 더티페이지(메모리에는 변경이 되었지만 디스크에는 아직 변경이 되지 않은 데이터)에 있는 데이터를 검색한다. 커밋되지 않은 데이터를 리드하기 때문에 더티리드 후 더티페이지가 롤백이 되면 잘못된 데이터를 읽어온 경우가 되어버린다.
- 아래 예시에서 트랜잭션 A가 트랜잭션을 끝마치지 못하고 롤백한다면 트랜잭션 B는 무효가 된 값을 읽고 처리한다.
- NON-REPEATABLE READ
- 같은 트랜잭션 내에서 READ시 값이 다르게 나오는 데이터 불일치 문제
- 하나의 트랜잭션에서 같은 쿼리를 두번 이상 수행할 때, 똑같은 쿼리임에도 다른 결과를 볼 수 있게 되는 현상
- 트랜잭션 중 데이터가 변경되면 문제가 발생할 수 있다.
- Phantom Read
- NON-REPREATABLE READ의 한 종류
- 하나의 트랜잭셩네서 일정 범위의 레코드를 두번이상 읽을 때, 똑같은 쿼리임에도 첫번째 쿼리에서 없던 레코드가 두번째 쿼리에서 나타나는 현상
트랜잭션 전파 타입
- 트랜잭션 경계에서 이미 진행중인 트랜잭션이 있을 어떻게 동작할지 결정하는 것
전파타입
- REQUIRED
- 현재 진행중인 트랜잭션이 존재하면 해당 트랜잭션을 사용한다.
- 존재하지 않으면 새로운 트랜잭션을 생성한다.
- 두 메서드가 하나의 트랜잭션으로 실행되기 때문에 어느 메서드에서 문제가 발생해도 실행했던 모든 쿼리가 롤백된다.
- SUPPORTS
- 진행중인 트랜잭션이 있다면 트랜잭션을 사용한다.
- 진행중인 트랜잭션이 없다면 트랜잭션 없이 메서드가 정상동작한다.
- MANDATORY
- REQUIRED와 달리 진행 중인 트랜잭션이 존재하지 않을 경우 예외가 발생한다.
- REQUIRES_NEW
- 항상 새로운 트랜잭션을 시작한다.
- 진행 중인 트랜잭션이 존재하면 기존 트랜잭션을 일시 중지하고 새로운 트랜잭션을 시작한다.
- 새로운 트랜잭션이 종료된 뒤에 기존 트랜잭션이 계속된다.
- NOT_SUPPORTED
- SUPPORT와 달리 진행 중인 트랜잭션이 존재할 경우 메서드가 실행되는 동안 트랜잭션을 일시 중지 되고 메서드 실행이 종료된 후에 트랜잭션을 계속 진행한다.
- 트랜잭션을 사용하지 않는 설정
- NEVER
- 메서드가 트랜잭션을 필요로 하지 않는다.
- 만약 진행 중인 트랜잭션이 존재하면 예외 발생
- NESTED
- 진행 중인 트랜잭션이 존재하면 그 안에 새로운 트랜잭션을 만드는 설정
- 중첩된 트랜잭션 2는 부모인 트랜잭션1의 커밋, 롤백에는 영향을 받는다.
- 트랜잭션2의 커밋 롤백에는 트랜잭션1이 영향을 받지 않는다.
Timeout
@Transactional(timeout=10)
- 초 단위로 트랜잭션 제한시간을 설정할 수 있는 속성
- 설정된 시간이 지나면 예외가 발생하며 롤백
- 따로 설정하지 않으면 timeout 속성은 지정되어 있지 않음
readOnly
@Transactional(readOnly=true)
- 트랜잭션 작업 안에서 update, insert, delete 작업이 일어나는 것을 방지
- 해당 옵션을 적용하면 flush 모드가 manual로 설정되어 jpa의 더티체킹 기능 무시 하여 성능향상에 도움을 줌
rollbackFor
@Transactional(rollbackFor=NoSuchElementException.class)
- 체크예외를 롤백 대상으로 삼고싶을 때 사용한다.
- 기본적으로 트랜잭션은 런타임 예외와 Error가 발생했을 때만 롤백
- 체크예외나 예외가 발생하지 않으면 커밋하도록 한다.
noRollbackFor
@Transactional(noRollbackFor={IOException.class, SqlException.class})
- 롤백 대상인 지정된 런타임 예외를 롤백하지 않고 커밋하도록 한다.
트랜잭션 메커니즘
BEGIN TRAN
UPDATE accounts
SET balance = balance - 10000
WHERE user = '구매자'
SET balance = balance + 10000
WHERE user = '판매자'
COMMIT TRAN
- UPDATE accounts SET balance = balance - 10000 WHERE user = '구매자' 쿼리 실행
- 업데이트에 필요한 데이터를 데이터 캐시에 요청을 하는데, 데이터 캐시에 해당 데이터가 없다.
- 데이터 파일에서 데이터를 가져와야 한다.
- 그리고 데이터 캐시에 필요한 데이터가 로드 된다.
User Balance 구매자 10,000 - 데이터가 로드 된 후, 업데이트를 하면 되는데 그 전에 로그 캐시에 로그를 기록해야 한다.
- ReDo로그와 UnDo로그에 기록을 한다.
- ReDo 로그
- 변경 후의 값을 기록한다.
-
트랜잭션_1 START 트랜잭션_1 UPDATE accounts 구매자.balance 0
- UnDo 로그
- 변경 전의 값을 기록한다.
-
로그_1 accounts 구매자.balance 10000
- ReDo 로그
- 로그 기록 후 데이터 캐시에 있는 값을 변경하면 된다.
User Balance 구매자 0 - UPDATE accounts SET balance = balance + 10000 WHERE user = '판매자' 쿼리 실행
- 판매자의 데이터가 없으므로 데이터 파일에서 데이터 캐시로 로드
User Balance 구매자 0 판매자 0 - ReDo로그와 UnDo로그에 기록을 한다.
- ReDo로그
-
트랜잭션_1 START 트랜잭션_1 UPDATE accounts 구매자.balance 0 트랜잭션_2 UPDATE accounts 판재마.balance 10000
-
- UnDo로그
-
로그_1 accounts 구매자.balance 10000 로그_2 accounts 판매자.balance 0
-
- ReDo로그
- 데이터 캐시의 데이터 업데이트
User Balance 구매자 0 판매자 10000 - 트랜잭션의 한 단위가 끝났다.
데이터 롤백 시 UnDo로그를 통해 롤백한다.
- UnDo를 통해서 역순으로 기록을하게 되면 데이터가 이전 상태로 원복 된다.
로그_1 accounts 구매자.balance 10000
로그_2 accounts 판매자.balance 0
User | Balance |
구매자 | 10000 |
판매자 | 0 |
예상치 못한 오류 발생 시 ReDo로그와 UnDo로그를 통해 복구한다.
- ReDo로그를 순차적으로 실행 해서 데이터들을 다시 일관성 있게 만들어 준다.
트랜잭션_1 START
트랜잭션_1 UPDATE accounts 구매자.balance 0
트랜잭션_2 UPDATE accounts 판재마.balance 10000
- Undo로그를 역순으로 실행하여 다시 커밋이 되지 않은 것들을 다시 이전 상태로 돌려준다.
로그_1 accounts 구매자.balance 10000
로그_2 accounts 판매자.balance 0
참고
'study' 카테고리의 다른 글
[Java]컬렉션(Collections) 정리 (0) | 2021.12.02 |
---|---|
[Spring]프로토타입과 스코프 (0) | 2021.12.02 |
[Spring] Scheduling - CronTask (0) | 2021.10.02 |
[AWS] AWS에는 무슨 서비스가 있을까? (0) | 2021.07.20 |
[java]JVM JRE JDK (0) | 2021.06.17 |