[DB] Transaction

박세건·2024년 2월 25일
0

CS 학습

목록 보기
3/23

트랜잭션

정의

  • 트랜잭션이란, DB의 상태를 변화시키는 기능을 수행하는 하나 이상의 쿼리를 모아놓은 작업의 단위 를 말합니다.

트랜잭션의 필요성

은행에서 A에서 B로 송금을 하려고 한다고 할때, A에서 돈을 빠져나갔지만 B로 입금이 되지 않았을 경우를 생각해보겠습니다.
이럴 때 A의 송금을 취소하거나, B의 계좌에 따로 송금을 시켜주면 되지만, 이러한 과정은 너무 번거롭고 위험합니다.
이러한 문제를 해결하기위해서 모든 거래가 완벽하게 끝난 후에만 거래가 완료 된것으로 승인하기로 했습니다.
만약 중간에 오류가 발생했을때에는 송금을 하기 이전에 상태로 되돌려놓는 것입니다.
이러한 방식으로 거래의 안정성을 확보할 수 있습니다.
이러한 방식을 위해 트랜잭션이 필요합니다.

트랜잭션의 종류

  • 활동 : 트랜잭션이 수행중인 상태를 의미합니다.

  • 실패 : 트랜잭션이 오류로 인해 중단된 상태를 의미합니다.

  • 부분완료 : 트랜잭션이 모든 연산을 실행했지만, commit되기 이전임을 나타냅니다.

  • 완료 : 트랜잭션이 모두 정상적으로 처리되었고 이를 DB에 영구적으로 저장하는 작업입니다.

  • 철회 : 트랜잭션의 처리중 문제점을 확인하고 이를 취소하는 상태입니다

    • 트랜잭션이 시작되기 이전의 상태로 되돌립니다. 이는 마지막 commit이 완료된 시점을 의미합니다.

    트랜잭션의 특성

  • 트랜잭션은 ACID라는 특성을 갖고 있습니다.

    • A : Atomicity(원자성)
      • 한 트랜잭션의 연산은 모두 성공하거나 또는 모두 실패가 되는 특성을 의미합니다.
    • C : Consistency(일관성)
      • 트랜잭션이 커밋된 이후에 DB의 상태(규칙)는 일관적(동일)이어야 한다는 성질 입니다.
    • I : Isolation(격리성)
      • 트랜잭션을 수행할때 다른 트랜잭션의 연산작업이 끼어들지 못하도록 보장하는 특성을 의미합니다.
    • D : Durablity(지속성)
      • 하나의 트랜잭션이 성공적으로 수행되었다면, 해당 기록은 DB에 영구적으로 보존되어야한다. (런타임 오류나 시스템 오류가 발생해도 영구적)

    ACID 원칙은 완벽하지 않다.

    만약 ACID의 원칙을 엄격하게 지킨다면 동시성이 떨어지게 되고 이는 비효율적입니다. 때문에 이러한 동시성을 확보하기 위해서 ACID의 원칙(독립성)을 희생하는 방법이 존재합니다.
    이 방법을 Transaction의 격리수준 이라고 합니다.

    트랜잭션의 격리 수준(isolation level)

  • 격리 수준 : 동시에 여러 트랜잭션이 처리될때 다른 트랜잭션에서 변경하거나 조회하는 데이터를 볼 수 있도록 허용하는 정도를 결정하는 것을 말합니다.

  • 고립정도가 심해진다면 성능은 저하되는 것입니다.

    격리 수준을 설정해서 어디까지 Lock을 설정할 것인지 자동으로 정해지는 것입니다.

Read Uncommitted

  • read uncommited 격리 수준에서는 트랜잭션의 내용이 commit이든 rollback 이든 상관없이 다 보여지는 것을 의미합니다.
  • 때문에 commited 하지 않아도 데이터를 조회할 수 있습니다 => Dirty Read.
  • 하나의 트랜잭션 안에서는 같은 데이터에 대한 select가 항상 같아야 한다(Repeatable Read)
  • 하지만 더티 리드 처럼 정합성(데이터가 서로 일치함)에 있어 위험한 문제가 있기에 RDBMS 표준에서는 격리 수준으로 인정하지 않습니다.

Read Committed

  • read commited는 말 그대로 commit 되어야만 다른 트랜잭션에서 조회할 수 있는 것을 의미합니다(Oracle 기본).
  • 하지만 트랜잭션이 실행된 후 커밋된 내용에 있어서 다른 결과를 내려줄 수 있는 상황이 존재하기에 정합성 문제는 해결되지 않습니다.
  • Non-Repeatable Read

Repeatable Read

  • repeatable read는 트랜잭션이 실행되기 이전에 커밋된 내용에 대해서만 조회할 수 있도록 하는 격리 수준입니다.(MySql 기본)
  • 이러한 특성으로 정합성 문제는 어느 정도 해결이 되었습니다.
  • 하지만 하나의 트랜잭션의 실행시간이 길어진다면 해당 시간만큼 멀티 버전을 관리(용량문제)해야한다는 단점이 있습니다.
    • 하지만 실제로 성능 차이는 read committed와 차이가 없습니다.
  • !!이 격리 수준에서는 Update한 데이터에 대해서는 정합성을 보장하지만 insert/delete는 보장되지 않습니다 때문에 pantom read가 발생하게 됩니다
    pantom read : 없었던 데이터를 조회하거나 이전에 조회가능하던 데이터가 사라지는 것

A와 B라는 사람이 있을때 A가 작업을 완료하고 commit을 하고 B가 작업을 완료하고 commit까지 해줘야 그 후에 B가 A가 작업한 결과를 확인할 수 있다. 그후에 다시 A가 B의 작업을 확인하고 싶다면 A는 다시 commit을 해줘야합니다.(B가 A가 commit한 후에 commit을 했기때문)

Serializable

  • 가장 단순하고 엄격한 격리 수준입니다.
  • 트랜잭션이 특정 테이블을 읽기 시작했다면 그 테이블의 데이터를 추가/변경/삭제 할 수 없습니다.
  • 데이터 정합성을 가장 잘 보장합니다.
  • 하지만 이러한 엄격한 격리 수준으로 동시 처리 능력이 떨어집니다.

격리 수준이 뭐가 좋다 나쁘다는 정할 수 없습니다. 어떤 전략으로 데이터를 다루도록 하는지가 중요합니다.

LOCK

Lock 이란, DB에 여러 사용자들이 접근하는 상황에서 세션이 트랜잭션을 시작하고 데이터를 수정하는 동안에 커밋이나 롤백 전까지 다른 세션에서 해당 데이터를 수정할 수 없게 막는 역할을 합니다.

  • 트랜잭션의 특성인 독립성을 지켜줍니다.
  • 수정 뿐만 아니라 조회할때도 Lock 을 사용할 수 있는데, 이때 select for update 구문을 사용해서 Lock을 획득합니다.
    • 예를 들어서 돈과 관련된 계산을 진행할때 다른 곳에서 금액을 변경하지 못해서 Lock을 가져갑니다.

Lock의 범위

  • 데이터베이스 : 전체 DB를 기준으로 Lock을 설정
    • 잘 사용하지 않지만, DB 업데이트나 소프트웨어 버전 업그레이드에 사용
  • 파일 : 파일을 기준으로 Lock을 설정
    • 파일이란, 테이블, row 등 과 같은 데이터가 쓰여지는 장소를 의미
    • 잘 사용되지는 않습니다.
  • 테이블 : 테이블을 기준으로 Lock을 설정
    • 전체 테이블에 영향을 줄때 주로 사용합니다. ex) DDL 사용 => 때문에 DDL Lock이라고도 합니다.
  • 페이지와 블럭 : 파일의 일부인 페이지와 블록을 기준으로
    • 잘 사용하지 않습니다.
  • 컬럼 : 컬럼을 기준으로 Lock을 설정
    • 이 범위는 리소스(자원)가 많이 들기에 잘 사용하지 않습니다.
  • 행 : DML에 대해 가장 기본적으로 사용하는 Lock

Lock의 종류

  • 공유 락(Shared Lock)
    • 주로 데이터를 조회(select)할때 사용합니다 read lock으로도 불립니다.
    • 데이터를 조회하는 것은 데이터 일관성에는 영향을 주지 않기때문에 공유 락 끼리는 동시에 접근이 가능합니다.
    • 즉, 데이터를 조회할때 그 데이터는 수정이 불가합니다.
  • 배타 락(Exclusive(독점) Lock)
    • 데이터를 변경할때 사용하고 write lock으로 불립니다.
    • 트랜잭션이 완료될 때 까지 다른 세션의 접근(select, insert...) 하는 것을 막습니다.
  • 업데이트 락(Update Lock)
    • 데이터를 수정하기 위해 베타 락을 걸기 전, 데드 락을 방지하기위해서 사용합니다.
    • Update 쿼리의 필터(Where)가 실행되는 과정에 적용됩니다.
  • 내재 락(Intent Lock)
    • 사용자가 요청한 범위에 대해 락을 걸 수 있을지에 대한 여부를 빠르게 파악하기 위해서 사용됩니다.

블로킹(Blocking)

블로킹이란, Lock들 끼리 경합이 발생해서 특정 세션이 작업을 진행하지 못하고 멈춘 상태를 의미합니다. 즉, 상대 Lock이 끝나기를 기다리고있는 것입니다.

  • 공유 락 - 배타 락
  • 배타 락 - 배타 락
    위와 같은 블로킹이 발생할 수 있습니다.

해결방법

  • 이를 해결하는 방법은 트래잭션을 commit과 rollback해주는 것과 SQL문장이 빠르게 실행되도록 리팩토링 하는 것

교착상태

교착상태란, 두 트랜잭션이 각각 Lock 을 설정하고 서로의 lock에 접근해서 값을 얻어려고 할때 트랜잭션이 commit, rollback 되기전까지 기다려야하는데 이때 양쪽의 트랜잭션이 엉켜서 서로 영원히 처리가 되지 않는 상태를 의미합니다.

  • 공유 락 - 베타 락
  • 배타 락 - 배타 락
    위와 같은 데드락이 발생할 수 있습니다.

해결방법

  • 예방 : 교착 상태 발생 조건 중 하나를 제거해서 예방합니다.
    • 단점 : 자원 낭비가 심합니다.
  • 회피 : 데드락 발생할 위험이 있는 자원이 생기면 자원 할당 요청을 보류합니다.
    • 자원을 할당한 후에도 안정 상태로 남아있는가를 확인합니다.
    • 단점 : 오버헤드(특정 기능을 수행하는데 드는 자원)가 많이 발생한다.
  • 탐지 : 빠르게 데드락을 발견하고 문제를 해결합니다.
  • 회복 : 교착 상태를 일으킨 프로세스를 종료하거나 할당된 자원을 해제합니다.

블로킹과 교착상태는 뭐가 다를까?

블로킹은 락끼리의 경합상태시 트랜잭션의 진행이 멈춰있는 현상을 말한다고 했습니다. 때문에 경합중인 트랜잭션들 중에서 하나의 트랜잭션이 일을 끝내고 commit한다면 이어서 다른 트랜잭션이 실행될 수 있는 것입니다. 때문에 영원하지 않습니다.
하지만, 교착상태는 서로가 서로의 트랜잭션을 기다리는 상태이기 때문에 영원히 끝나지 않습니다.

profile
멋있는 사람 - 일단 하자

0개의 댓글

관련 채용 정보