DB 트랜잭션과 LOCK


DB Transaction

  • 논리적인 작업의 단위(사용자 입장)
    • 계좌 이체
  • 데이터베이스의 상태를 변경하는 작업의 단위(시스템 입장)
  • 트랜잭션으로 묶인 연산들은 All Or Nothing - 모두 실행되거나 모두 실행되지 않거나.
  • 트랜잭션의 설계가 중요하다.


Transaction과 lock의 차이

  • Transaction - 정합성을 보장하기 위한 기능
  • Lock - 동시성을 제어하기 위한 기능


트랜잭션이 지켜야하는 원칙 - ACID

원자성(Atomic, All or Nothing)

  • 하나의 트랜잭션을 이루는 연산들모두 실행되거나 모두 실행되지 않거나


일관성(Consistency)

  • 트랜잭션의 실행이 완료되면 데이터베이스는 일관된 상태를 유지
  • 트랜잭션이 완료될 때 여러 제약조건에 맞는 상태를 보장해야하는 성질
  • 성공적으로 수행된 트랜잭션은 정당한 데이터들만을 데이터베이스에 반영해야 한다.
  • 트랜잭션 전/후의 데이터베이스 상태는 각각 일관성이 보장되는 서로 다른 상태가 되어야 한다.
    • ex: A, B간 계좌 이체 시 트랜잭션 전/후의 A, B 잔고 상태는 다르지만 총합은 같다.
  • 명시적인 일관성기본키, 외래키 제약과 같은 명시적인 무결성 제약 조건
  • 비명시적 일관성은 “계좌 이체 후 두 계좌의 잔고 합이 같아야 한다”와 같은 일관성


독립성, 격리성(Isolation)

  • 하나의 트랜잭션이 수행되는 동안 다른 트랜잭션이 끼어들 수 없다. (동시성 문제)
  • 여러 트랜잭션이 동시에 수행되더라도 각각의 트랜잭션은 다른 트랜잭션의 수행에 영향을 받지 않고 독립적으로 수행되어야 한다.
  • 한 트랜잭션의 중간 결과가 다른 트랜잭션에게 숨겨져야 한다.
  • 트랜잭션이 진행되는 중간 상태의 데이터를 다른 트랜잭션이 볼 수 없도록 보장
  • 격리 레벨로 설정 가능하다.


ACID 원칙은 완벽히 지켜지지 않는다. - Transaction의 Isolation Level

실제로 ACID 원칙은 종종 지켜지지 않는다. ACID 원칙을 strict 하게 지키려면 동시성이 매우 떨어지기 때문

그렇기 때문에 보통 DB 엔진은 ACID 원칙을 조금 희생하여 동시성을 얻을 수 있는 방법을 제공한다. 바로 Transaction Isolation Level

Isolation 원칙을 덜 지키는 level을 사용할 수록 문제가 발생할 가능성은 커지지만 더 높은 동시성을 얻을 수 있다.

DB 엔진은 Isolation Level에 따라 서로 다른 Locking 전략을 취한다. 요컨대 isolation level이 높아질수록 더 보수적인 Lock을 거는 것이다.


Lock

Oracle을 비롯한 대부분의 DB는 Transaction의 ACID 원칙동시성을 최대한 보장하기 위해 다양한 종류의 LOCK을 사용한다.

  • Row-level lock
    • 가장 기본적인 lock테이블의 row마다 걸리는 row-level lock이다.
    • 여기에는 크게 shared-lock(s-lock)exclusive-lock(x-lock)이 존재한다.


  • shared-lock
    • read(=select)에 대한 lock이다. 일반적으로 SELECT 쿼리는 동일한 리소스(table row)에 동시에 사용(접근)이 가능하다.
    • 다시말해 여러 Transaction이 동시에 동일한 row에 s-lock을 걸 수 있다.
    • 하지만 s-lock이 걸린 row에 대해서는 x-lock이 불가능하다.


  • exclusive-lock
    • write(update, delete)에 대한 lock이다.
    • x-lock이 걸려있는 row에는 다른 Transaction들이 s-lock이나 x-lock을 걸 수 없다.
    • 즉, x-lock이 걸려있는 row는 다른 트랜잭션들이 read, write 모두 불가능하다.


요약하자면 s-lock을 사용하는 트랜잭션끼리는 동일한 row에 접근이 가능하다. 반면 x-lock이 걸린 row는 다른 어떤 트랜잭션도 접근이 불가능하다.


Lock 해제 타이밍

Transaction이 진행되는 동안 수 많은 lock들을 데이터베이스에 걸게 된다. 이러한 lock들은 모두 transaction commit 또는 rollback 될 때 함께 unlock된다.

트랜잭션 사용 시 주의

  • 트랜잭션은 꼭 필요한 최소의 코드에만 적용되어야 한다. → 트랜잭션의 범위를 최소화
    • 단위 스레드가 커넥션 소유 시간이 길어진다다른 스레드가 커넥션 획득을 위해 대기해야 하는 상황이 발생
  • 교착 상태 발생 가능
    • 복수의 트랜잭션 사용 시 각 트랜잭션이 사용하는 자원에 LOCK을 걸고 서로의 자원을 요구하면 DEAD LOCK이 발생


참고 자료