locking

김예진·2023년 1월 16일

✨잠금이란?

  • 하나의 트랜잭션이 실행하는 동안 특정 데이터 항목에 대해서 다른 트랜잭션이 동시에 접근하지 못하도록 상보배제 기능을 제공하는 기법
  • 하나의 트랜잭션이 데이터 항목에 대하여 잠금을 설정하면, 잠금을 설정한 트랜잭션이 해제할 때까지 데이터를 독점적을 사용할 수 있음

✨잠금에 사용되는 연산

  • 잠금 기법은 기본적으로 lock연산과 unlock 연산을 사용함

✨잠금 연산의 종류

  • 잠금 연산은 데이터에 대한 연산의 성격에 따라 공유잠금과 배타잠금으로 나뉨
  • 모든 트랜잭션은 데이터 항목에 대한 접근을 시도할 때 둘 중 하나의 잠금 방법을 사용함
  • 공유잠금과 배타잠금 모두 잠금을 해제할 경우에는 unlock 연산을 이용함

공유잠금(S-lock)

  • 공유잠금을 설정한 트랜잭션은 데이터 항목에 대해 읽기 연산만 가능
    ex) T1에서 x에 대해 S-lock을 설정했다면, T1은 read(x) 연산만 가능
  • 하나의 데이터 항목에 대해 여러 개의 공유잠금이 가능함
    ex) T1에서 x에 대해 S-lock을 설정한 경우, 동시에 T2에서도 x에 대해 S-lock을 설정할 수 있음
  • 다른 트랜잭셩도 읽기 연산(read) 만을 실행할 수 있음
    ex) T1에서 x에 대해 S-lock을 설정했다면, T2에서도 T1이 S-lock(x)을 실행하는 동안 read(x) 연산만 가능하다.

배타잠금(X-lock)

  • 배타잠금을 설정한 트랜잭션은 데이터 항목에 대해서 읽기 연산과 쓰기 연산 모두 가능함
    ex) T1에서 x에 대해 S-lock을 설정했다면, T1은 read 연산과 write 연산 모두 가능함
  • 하나의 데이터 항목에 대해서는 하나의 배타잠금만 가능함(동시에 여러 개의 배타잠금을 불가능함)
    ex) T1에서 x에 대해 X-lock을 설정했다면, T1에서 unlock(x)를 하기전까지 T2에서 x에 대해 X-lock을 설정할 수 없음
  • 다른 트랜잭션은 읽기 연산과 쓰기 연산 모두 불가능함
    ex) T1에서 x에 대해 X-lock을 설정했다면, T2에서는 T1에서 unlock(x)를 하기 전까지 read(x), write(x) 연산이 모두 불가능함

여러 트랜잭션이 하나의 데이터를 동시에 읽을 때(read 연산)는 문제가 되지 않는다. 그러나 어느 한 쪽이라도 쓰는 경우(write 연산)에는 트랜잭션 간의 상호 간섭으로 인해 잘못된 결과가 발생할 수 있다. 그러므로 읽기 연산(read)을 실행하기 위해 설정하는 S-lock은 여러 트랜잭션에서 동시에 사용 가능하지만, 쓰기 연산(write)을 실행하기 위해 설정하는 X-lock은 동시에 사용할 수 없다고 이해하면 된다.

✨잠금 설정 규칙

  • 트랜잭션은 데이터 항목 x에 대해 read 연산을 실행하기 전, 공유잠금(S-lock)이나 배타잠금(X-lock) 중 하나를 실행해야 함
  • write 연산을 실행하기 위해서는 배타잠금(X-lock)을 실행해야 함
  • 연산 종료 후에는 unlock 연산을 실행해야 함
  • 공유잠금(S-lock)이나 배타잠금(S-lock) 연산 실행 후에만 Unlock 연산을 실행할 수 있음

✨잠금 단위

  • 잠금 단위는 잠금의 대상이 되는 데이터 객체의 크기를 의미함

  • 작게는 레코드의 필드 값, 하나의 레코드, 물리적 입출력 단위가 되는 디스크 블록이 될 수도 있으며, 크게는 테이블이나 데이터베이스까지 하나의 잠금 단위가 될 수 있음

  • 잠금 단위가 클수록 동시성(병행성) 수준은 낮아지고, 동시성 제어 기법은 간단해짐

  • 잠금 단위가 작을수록 동시성(병행성) 수준은 높아지고, 관리는 복잡해짐

ex) 잠금 단위가 레코드일 경우 vs 테이블일 경우

  • 레코드: 두 개의 트랜잭션이 하나의 테이블에 대해 연산을 수행하더라도, 접근하는 레코드가 서로 다르면 동시에 실행이 가능함
    그러나 접근하는 레코드마다 일일이 잠금을 설정해야 하므로 관리는 복잡해짐
  • 테이블: 동시에 실행이 불가능하지만, 테이블 하나에만 잠금 설정이 필요하므로 관리가 쉬움

✨잠금의 한계

  • 잠금은 대부분의 DBMS에서 사용되는 방식이지만 다음과 같은 한계가 존재함
  1. 직렬 가능한 스케줄이 항상 보장되지 않는다(2단계 잠금 규약으로 해결)
  • 직렬성이란?: 각각의 트랜잭션이 동시에 수행되더라도 그 결과가 순차적으로 트랜잭션이 수행된 결과와 같은 경우를 말함(스케줄 동치)
  1. 교착상태가 발생할 수 있다
  • 교착상태란?

트랜잭션 T14와 T15가 동시에 실행하는데 T14에서 write(x) 연산과 X-lock(y) 연산 사이에 T15가 실행된다고 가정해보자.

(T14) X-lock(x) ··· T14가 x에 대해 X-lock을 얻고

(T15) S-lock(y) ··· 후에 T15가 y에 대해 S-lock을 얻는다.

여기까지는 서로 다른 데이터 항목 x, y에 대해 잠금을 설정한 것이므로 문제가 없다.

(T15) S-lock(x) ··· 그 다음 T15가 x에 대해 S-lock를 요청했을 때, T14가 이미 X-lock을 보유하고 있기 때문에 T14가 unlock하기 전까지 대기해야 한다.

(T14) X-lock(y) ··· T14가 y에 대해 X-lock을 요청하면, 이미 T15가 y에 대한 S-lock을 얻었기 때문에 T14 또한 T15가 unlock하기 전까지 대기하게 된다.

결국 T14, T15가 모두 대기 상태에 들어가 더 이상 진행하지 못하게 되고, 이런 상태를 교착상태(deadlock)라고 한다. 교착상태에 빠지면 외부에서 강제로 트랜잭션을 중단하거나 잠금을 해제하지 않는 이상 무한정 대기 상태로 남게 된다.

2단계 잠금 규약(2PL)

  • 2PL은 잠금을 설정하는 단계와 해제하는 단계로 나누어 수행
  • 확장단계(growing phase): 트랜잭션이 lock 연산만 수행할 수 있고 unlock 연산은 수행할 수 없는 단계
  • 축소단계(shrinking phase): 트랜잭션이 unlock 연산만 수행할 수 있고 lock 연산은 수행할 수 없는 단계

-2PL은 데이터 오류 가능성을 사전에 예방할 수 있고 알고리즘이 간단하며 직렬 가능한 스케줄을 보장하는 방법 중 하나임
-하지만 2PL로도 교착상태 문제는 해결할 수 없음 오른쪽 그림이 2PL을 준수하지만 교착상태가 발생한 사례에 해당함
-이 문제를 해결하는 가장 간단한 방법으로는 각 트랜잭션을 시작하기 전에 모든 필요한 잠금을 동시에 설정한는 방법이 있음 또는 교착상태 회피 방법이나 탐지 방법을 통해 교착상태를 해결해야 함

2PL은 연쇄복귀문제도 발생할 수 있음

  • 연쇄복귀문제란?: 병행 수행되던 둘 이상의 트랜잭션 중 어느 한 트랜잭션에 오류가 발생하여 Rollback 하는 경우 다른 트랜잭션들도 함께 Rollback 되는 현상을 말함

이는 엄격한 2PL로 해결 가능

  • 엄격한 2단계 잠금 규약
    -엄격한 2PL은 모든 X-lock에 대한 unlock 연산을 트랜잭션이 완전히 완료된 후에 실행하는 것
    -엄격한 2PL을 사용하면 트랜잭션에 의해 갱신된 데이터를 다른 트랜잭션이 읽거나 쓸 가능성을 원천적으로 봉쇄할 수 있어 연쇄 복귀 문제를 해결할 수 있음
    -현재 대부분의 RBMS에서 엄격한 2PL 규약을 이용하여 동시성 제어를 구현함
    엄격한 2단계 잠금 규약(strict 2-Phase Locking protocol : strict 2PL)

출처
https://medium.com/pocs/%EB%8F%99%EC%8B%9C%EC%84%B1-%EC%A0%9C%EC%96%B4-%EA%B8%B0%EB%B2%95-%EC%9E%A0%EA%B8%88-locking-%EA%B8%B0%EB%B2%95-319bd0e6a68a

0개의 댓글