Database - 트랜잭션(교착상태, 격리 수준)

choko's avatar
Jun 29, 2024
Database - 트랜잭션(교착상태, 격리 수준)
 

트랜잭션

  • 데이터베이스의 상태를 변화시키기 위해 수행하는 작업 단위
  • 트랜잭션의 연산
    • commit
      • 하나의 트랜잭션이 성공적으로 종료된 후, 갱신 연산이 완료되었다고 관리자에게 알려주고 최종적으로 데이터베이스에 반영하는 연산
    • rollback
      • 트랜잭션이 비정상적으로 종료되어 DB의 일관성을 잃었을 때, 지금까지의 연산의 결과를 취소하고 트랜잭션 수행 이전의 상태로 돌아가는 연산
  • 논리적인 작업 set을 모두 완벽하게 처리하거나(commit), 또는 처리하지 못할 경우 원 상태로 복구해서 작의 일부만 적용되는 현상이 발생하지 않게 만들어 주는(rollback) 기능
    • 예시) 사용자 A가 사용자 B에게 만원을 송금한다. * 이때 DB 작업 - 1. 사용자 A의 계좌에서 만원을 차감한다 : UPDATE 문을 사용해 사용자 A의 잔고를 변경 - 2. 사용자 B의 계좌에 만원을 추가한다 : UPDATE 문을 사용해 사용자 B의 잔고를 변경 현재 작업 단위 : 출금 UPDATE문 + 입금 UPDATE문 → 이를 통틀어 하나의 트랜잭션이라고 한다. - 위 두 쿼리문 모두 성공적으로 완료되어야만 "하나의 작업(트랜잭션)"이 완료되는 것이다. `Commit` - 작업 단위에 속하는 쿼리 중 하나라도 실패하면 모든 쿼리문을 취소하고 이전 상태로 돌려놓아야한다. `Rollback`
       

트랜잭션 특징(ACID)

  • 원자성(Atomicity)
    • 트랜잭션이 DB에 모두 반영되거나, 혹은 전혀 반영되지 않아야 한다.
  • 일관성(Consistency)
    • 트랜잭션의 작업 처리 결과는 항상 일관성이 있어야 한다.
    • cascade
  • 독립성(Isolation)
    • 둘 이상의 트랜잭션이 동시에 병행 실행되고 있을 때, 어떤 트랜잭션도 다른 트랜잭션 연산에 끼어들 수 없다.
    • 트랜잭션 격리 수준
  • 지속성(Durability)
    • 트랜잭션이 성공적으로 반영되면, 결과는 영구적으로 반영되어야 한다.
    •  
 

Undo, Redo

notion image
 
서버에 장애가 발생하거나 인스턴스가 비정상 종료했을 때, RedoUndo를 사용해 데이터를 복구하고 rollback을 진행한다.
  • Undo
    • 최신 데이터를 오래된 데이터로 만들기 위해 존재함
    • 트랜잭션을 이전 상태로 되돌리는것을 의미
    • 읽기 일관성을 지키기 위해 Undo를 사용한다.
      • 멀티 유저의 읽기 일관성 보호
    • 데이터가 변경되면 Undo의 세그먼트가 생성되며, Undo 세그먼트는 트랜잭션과 일대일로 대응한다.
  • Redo
    • 오래된 데이터를 최신 데이터로 만들기 위해 존재
    • 이전 상태로 되돌아간 후, 실패가 발생하기 전까지의 과정을 그대로 따라가는걸 의미한다.
 

트랜잭션의 교착상태

  • 복수의 트랜잭션을 사용하면 교착상태가 일어날 수 있다.
  • 대표적으로, MVCC(다중 버전 동시성 제어)가 있다.
    • 동시성 제어
      • DBMS에서 다수의 사용자 사이에서 동시에 작용하는 다중 트랜잭션의 상호간섭 작용에서 DB를 보호하는 것
      • LOCK과 같은 기능을 통해 동시성 제어를 한다. 하지만 Locking 메커니즘에는 문제점이 있다.
        • 읽기 작업과 쓰기 작업이 서로 방해를 일으키기 때문에 동시성 저하 발생
    • MVCC(다중 버전 동시성 제어, Multi-Version Concurrency Control)
      • 동시 접근을 허용하는 데이터베이스에서 동시성을 제어하기 위해 사용하는 방법 중 하나이다.
        • MVCC에서는, 변경이 진행 중인 레코들을 만나더라도 대기하지 않는다.
        • 데이터를 변경할 때마다, 그 변경사항을 UNDO 영역에 저장한다.
        • 데이터를 읽다가 쿼리 또는 트랜잭션 시작 시점 이후에 변경된 값을 발견하면, UNDO 영역에 저장된 정보를 이용해 쿼리 시점의 일관성 있는 버전을 생성하고 읽는다.
          • 따라서 하나의 데이터에 여러 버전의 데이터가 존재하게 된다.
      • 장점
        • 일반적인 RDBMS보다 매우 빠르게 작동
      • 단점
        • 사용하지 않는 데이터가 계속 쌓이므로, 데이터를 정리하는 시스템이 필요
        •  
 
 

트랜잭션 격리 수준

  • 트랜잭션에서 일관성 없는 데이터를 허용하도록 하는 수준
  • DB는 ACID 특징과 같이 트랜잭션이 독립적인 수행을 하도록 한다.
    • 따라서 Locking을 통해 트랜잭선이 DB를 다루는 동안 다른 트랜잭션이 관여하지 못하게 막아야 한다.
    • 독립성을 챙기며 지나치게 성능 저하가 일어나지 않도록, 효율적인 Locking 방법이 필요함
  • 격리 수준의 종류
    • Read Uncommitted (level 0)
      • SELECT 문장이 수행되는 동안 해당 데이터에 Shared Lock이 걸리지 않는 계층
      • 데이터의 일관성을 유지하는것이 불가능함
      • 사용자1A라는 데이터를 B라는 데이터로 변경하는 동안 사용자2는 아직 완료되지 않은(Uncommitted) 트랜잭션이지만 데이터B를 읽을 수 있다
    • Read Committed (level 1)
      • SELECT 문장이 실행되는 동안 해당 데이터에 Shared Lock이 걸리는 계층
      • Commit이 일어나는 트랜잭션만 조회 가능, 현재 대부분의 SQL 서버가 defulat로 사용
      • 사용자1이 A라는 데이터를 B라는 데이터로 변경하는 동안 사용자2는 해당 데이터에 접근이 불가능함
    • Repeatable Read (level 2)
      • Undo 공간에 백업해두고 실제 레코드 값을 변경한다. → MVCC 방식 사용
        • 백업된 데이터는 불필요하다고 판단하는 시점에 주기적으로 삭제한다.
        • Undo에 백업된 레코드가 많아지면 MySQL 서버의 처리 성능이 떨어질 수 있다.
        • 트랜잭션마다 트랜잭션 ID를 부여하여 트랜잭션 ID보다 작은 트랜잭션 번호에서 변경한 것만 읽게 된다
      • MYSQL에서 사용하는 레벨
    • Serializable (level 3)
      • 트랜잭션들이 동시에 일어나지 않고, 순차적으로 실행되는 것처럼 동작
      • 거의 사용되지 않는다
       
       

      낙관적 락과 비관적 락

    • 낙관적 락(Optimistic Lock)
      • 데이터 수정 시점에 충돌이 발생하는지를 확인하며, 충돌이 발생하면 트랜잭션을 실패시키고 다시 시도하도록 한다.
        • 다중 사용자 환경에서 데이터 경합이 드물다고 가정하고, 데이터 액세스 시 락을 걸지 않고 변경을 시도하는 동시성 제어 메커니즘
      • 데이터에 버전 번호나 타임스탬프를 부여하여, 커밋 시점에 현재 데이터의 버전과 수정하려는 데이터의 버전을 비교
        • → 만약 버전이 일치하면 변경 사항을 커밋하고, 버전을 증가시킨다.
          → 버전이 불일치하면 다른 트랜잭션에 의해 데이터가 변경된 것이므로, 현재 트랜잭션을 롤백하고 재시도하거나 오류를 반환한다.
      • DB에서 제공해주는 특징을 사용하는 것이 아닌, Application Level에서 잡아주는 Lock이다.
        • 개발자가 직접 롤백 처리를 해줘야 한다.
      • 사용 예시(JPA)
        • entityManager.find(MyEntity.class, id, LockModeType.OPTIMISTIC);
      • 특징
          1. 경량화: 락을 사용하지 않으므로 오버헤드가 적다
          1. 낮은 경합 환경에 적합: 데이터 충돌이 드물게 발생하는 환경에서 효율적
          1. 낮은 대기 시간: 락을 기다릴 필요가 없어 응답 속도가 빠르다
          1. 재시도 필요성: 충돌이 발생하면 트랜잭션을 재시도해야함
           
    • 비관적 락(Pessimistic Lock)
      • 데이터 경합이 빈번하게 발생할 것으로 가정하고, 데이터에 접근하는 동안 다른 트랜잭션이 해당 데이터에 접근하지 못하도록 락을 거는 동시성 제어 메커니즘
      • 트랜잭션이 시작될 때 Shared Lock(공유락, 트랜잭션 읽기를 할 때 사용하는 락) 또는 Exclusive Lock(배타락, 데이터를 변경할 때 사용하는 락)을 걸고 시작하는 방법
      • 먼저 Exclusive Lock을 가져간 트랜잭션이 Commit을 완료해야만, 다른 트랜잭션이 업데이트를 진행할 수 있다.
      • Repeatable Read 또는 Serializable 정도의 격리성 수준 제공
      • 특징
          1. 높은 신뢰성: 데이터 충돌을 사전에 방지하여 데이터 무결성을 보장
          1. 높은 경합 환경에 적합: 다수의 트랜잭션이 동시에 동일한 데이터를 수정하는 환경에서 효과적
          1. 락으로 인한 대기 발생: 락으로 인해 다른 트랜잭션이 대기해야 하므로 응답 시간이 증가할 수 있음
          1. 데드락 위험성: 여러 트랜잭션이 서로 락을 기다리며 교착 상태에 빠질 수 있다
       
    • 낙관적 락 vs 비관적 락
      • 기본적으로 성능 자체는 낙관적 락이 더 좋음(트랜잭션이 필요하지 않기 때문)
      • 하지만 충돌이 많이 일어나는 경우, 낙관적 락은 Version Update 처리와 수동 에러 처리로 인한 오버헤드가 더 심해져 비관적 락이 더 좋은 선택지가 될 수도 있다.
      개념
      설명
      특징
      사용 사례
      낙관적 락
      데이터 수정 시점에 충돌이 발생하는지를 확인하며, 충돌이 발생하면 트랜잭션을 실패시키고 다시 시도하도록 한다
      - 락 오버헤드가 없음 - 충돌 시 재시도 필요 - 낮은 경합 환경에 적합
      - 읽기 위주의 웹 애플리케이션 - 분산 시스템
      비관적 락
      데이터에 접근하는 동안 다른 트랜잭션이 해당 데이터에 접근하지 못하도록 공유락/배타락을 거는 동시성 제어 메커니즘
      - 높은 신뢰성 - 락으로 인한 대기 발생 - 높은 경합 환경에 적합
      - 금융 거래 시스템 - 재고 관리 시스템

공유락, 배타락, 레코드락

  • 공유락(Shared Lock)
    • 트랜잭션이 데이터를 읽는 동안 다른 트랜잭션도 해당 데이터를 읽을 수 있지만, 쓰기는 할 수 없도록 제한하는 락의 한 종류
    • 트랜잭션이 데이터를 읽으려고 할 때 공유락을 건다.
    • 다수의 읽기 작업을 병렬로 처리하여 성능을 높일 수 있고, 데이터의 일관성을 유지함
    • 쓰기 지연이 발생할 수 있고, Lock 오버헤드가 일어날 수 있다.
    • 사용 예시(JPA)
      • entityManager.find(MyEntity.class, id, LockModeType.PESSIMISTIC_READ);
       
  • 배타락(Exclusive Lock)
    • 트랜잭션이 데이터를 수정하는 동안 다른 트랜잭션이 해당 데이터에 대한 읽기나 쓰기를 모두 할 수 없도록 제한
    • 트랜잭션이 데이터를 수정하려고 할 때 배타락을 건다.
    • 데이터 수정 시 높은 수준의 일관성과 무결성을 보장하고, 충돌을 사전에 방지해 오류를 최소화한다.
    • Lock으로 인한 성능 저하가 발생할 수 있고, 데드락이 발생할 수 있다.
    • 사용 예시(JPA)
      • entityManager.find(MyEntity.class, id, LockModeType.PESSIMISTIC_WRITE);
       
  • 레코드 락(Record Lock)
    • 데이터베이스에서 특정 행(row) 또는 레코드에 대해 적용되는 락으로, 해당 레코드에 대한 동시 접근을 제어하기 위해 사용
      • 보다 세밀한 수준의 Lock 설정에 사용된다.
    • 세밀한 동시성 제어: 레코드 수준에서 락을 관리하여 동시성을 높이고 경합을 줄일 수 있지만, 복잡성이 증가한다.
개념
설명
특징
사용 사례
공유 락
데이터를 읽는 동안 다른 트랜잭션의 읽기는 허용하고 쓰기는 제한하는 락
- 동시 읽기 허용 - 쓰기 충돌 방지 - 읽기 작업이 빈번한 환경에 적합
- 보고서 생성 시스템 - 뉴스 사이트
배타적 락
데이터를 수정하는 동안 다른 트랜잭션의 모든 접근을 제한하는 락
- 강력한 일관성 보장 - 높은 경합 가능성 - 중요한 데이터 수정 작업에 적합
- 금융 거래 - 주문 처리 시스템
레코드 락
특정 레코드에 대해 적용되는 락으로, 세밀한 수준의 동시성 제어를 가능하게 함
- 동시성 향상 - 복잡성 증가 - 대규모 데이터베이스 시스템에 적합
- 온라인 거래 시스템 - 다중 사용자 편집 시스템
Share article

Tom의 TIL 정리방