[DB]트랜잭션 정리

에이든의 트랜잭션 매커니즘, 샐리, 예지니어스의 트랜잭션 테코톡을 듣고 정리한 글 입니다.

 

트랜잭션

  • 여러 쿼리를 논리적으로 하나의 작업으로 묶어주는 것
  • 하나의 트랜잭션은 커밋 혹은 롤백된다.
  • 데이터베이스에 저장된 데이터베이스의 무결성과 동시성의 성능을 지키기위해 트랜잭션의 설정이 중요

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

 

  1. UPDATE accounts SET balance = balance - 10000 WHERE user = '구매자' 쿼리 실행
  2. 업데이트에 필요한 데이터를 데이터 캐시에 요청을 하는데, 데이터 캐시에 해당 데이터가 없다.
  3. 데이터 파일에서 데이터를 가져와야 한다.
  4. 그리고 데이터 캐시에 필요한 데이터가 로드 된다.
    User Balance
    구매자 10,000
  5. 데이터가 로드 된 후, 업데이트를 하면 되는데 그 전에 로그 캐시에 로그를 기록해야 한다.
  6. ReDo로그와 UnDo로그에 기록을 한다.
    • ReDo 로그
      • 변경 후의 값을 기록한다.
      • 트랜잭션_1 START
        트랜잭션_1 UPDATE accounts 구매자.balance 0
    • UnDo 로그
      • 변경 전의 값을 기록한다.
      • 로그_1 accounts 구매자.balance 10000
  7. 로그 기록 후 데이터 캐시에 있는 값을 변경하면 된다.
    User Balance
    구매자 0
  8. UPDATE accounts SET balance = balance + 10000 WHERE user = '판매자' 쿼리 실행
  9. 판매자의 데이터가 없으므로 데이터 파일에서 데이터 캐시로 로드
    User Balance
    구매자 0
    판매자 0
  10. ReDo로그와 UnDo로그에 기록을 한다.
    •  ReDo로그
      • 트랜잭션_1 START
        트랜잭션_1 UPDATE accounts 구매자.balance 0
        트랜잭션_2 UPDATE accounts 판재마.balance 10000
    • UnDo로그
      • 로그_1 accounts 구매자.balance 10000
        로그_2 accounts 판매자.balance 0
  11. 데이터 캐시의 데이터 업데이트
    User Balance
    구매자 0
    판매자 10000
  12. 트랜잭션의 한 단위가 끝났다.

 

데이터 롤백 시 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

댓글



Designed by JB FACTORY