[데이터베이스] Lock

Yoon Uk·2023년 8월 24일
0

데이터베이스

목록 보기
19/20
post-thumbnail
post-custom-banner

DB Lock

DB Lock이란 데이터베이스에서 동시성 제어를 위해 사용하는 기능입니다.

DB Lock은 트랜잭션을 수행하는 동안 데이터를 보호하고 다른 트랜잭션으로부터의 접근을 제한합니다.

DB Lock은 데이터의 일관성과 무결성을 보장하는데 중요한 역할을 합니다. 하지만, DB Lock은 잘못 사용하면 성능 저하나 교착 상태와 같은 문제를 야기할 수 있습니다. 따라서, DB Lock을 적절하게 설계하고 관리하는 것이 필요합니다.

공유 Lock과 배타적 Lock

DB Lock에는 공유 Lock배타적 Lock이 있습니다.
공유 Lock배타적 Lock은 데이터베이스에서 동시성 제어를 위해 사용되는 기법입니다.

공유 Lock은 여러 트랜잭션이 동일한 자원에 대해 읽기 작업을 수행할 수 있도록 허용하는 반면, 배타적 Lock은 한 트랜잭션만이 자원에 대해 쓰기 작업을 수행할 수 있도록 허용합니다. 이렇게 함으로써, 데이터의 일관성과 무결성을 보장할 수 있습니다.

공유 Lock

다른 트랜잭션이 잠긴 객체를 읽고 다른 공유 Lock을 생성하는 것은 허용하지만, 쓰기나 배타적 Lock을 생성하는 것을 허용하지 않는 잠금입니다.

  • 공유 Lock은 읽기 작업을 위해 사용됩니다.
  • 공유 Lock은 다른 트랜잭션이 동일한 데이터에 공유 Lock을 걸 수 있습니다.
    • 즉 다른 트랜잭션이 읽고 있는 행을 읽을 수 있습니다.
  • 공유 락이 걸려있는 행에 베타 락을 걸 수는 없습니다.
    • 즉, 해당 공유 락이 해제될 때까지 쓰기 불가능합니다.

배타적 Lock

동일한 행에 다른 트랜잭션을 생성하는 것을 허용하지 않는 잠금입니다.

  • 배타적 Lock은 쓰기 작업을 위해 사용됩니다.
  • 배타적 Lock은 다른 트랜잭션이 동일한 데이터에 어떤 Lock도 걸 수 없습니다.
  • 동일한 행에 다른 트랜잭션을 생성하는 것을 허용하지 않는 잠금입니다.
  • 다른 트랜잭션에서 배타적 Lock을 생성할 수 없기 때문에 쓰기가 불가능합니다.
  • 다른 트랜잭션에서 공유 Lock을 생성할 수 없습니다. 단, 락을 쓰지 않는 읽기는 가능합니다.

예시

예를 들어, A와 B가 같은 계좌에서 출금을 하려고 할 때, 공유 Lock배타적 Lock이 적용되는 과정은 다음과 같습니다.

  1. A가 계좌 잔액을 조회하기 위해 공유 Lock을 걸고 읽기 작업을 수행합니다.
  2. B도 계좌 잔액을 조회하기 위해 공유 Lock을 걸고 읽기 작업을 수행합니다.
  3. A가 출금하기 위해 배타적 Lock을 요청합니다. 하지만 B가 아직 공유 Lock을 해제하지 않았으므로, A는 대기 상태가 됩니다.
  4. B가 출금하기 위해 배타적 Lock을 요청합니다. 하지만 A도 이미 배타적 Lock을 요청하고 있으므로, B도 대기 상태가 됩니다.
  5. 이 상황에서는 데드락이 발생하므로, 시스템은 데드락 탐지 알고리즘을 통해 데드락을 해결하고, 하나의 트랜잭션에게만 배타적 Lock을 부여합니다.
  6. 배타적 Lock을 부여받은 트랜잭션은 쓰기 작업을 수행하고, Lock을 해제합니다.
  7. 나머지 트랜잭션은 배타적 Lock을 부여받고, 쓰기 작업을 수행하고, Lock을 해제합니다.

이처럼, 공유 Lock과 배타적 Lock은 데이터베이스에서 동시성 제어를 위한 중요한 역할을 합니다.

공유 Lock과 배타적 Lock의 핵심

공유 Lock과 배타적 Lock의 핵심은 읽기 쓰기가 아니라 락 사이 호환 여부입니다.

공유 Lock은 같은 공유 Lock을 허용하기 때문에 읽기가 가능하고, 쓰기에 필요한 배타적 Lock을 불허하기 때문에 쓰기가 불가능 한 것이며,

배타적 Lock은 락을 사용하는 읽기(Locking Reads)인 경우에는 불가능하며 락을 사용하지 않는 읽기(Consistent Nonlocking Reads)인 경우에는 가능합니다.

MySQL 8.0 에서의 공유 Lock, 배타적 Lock

사용 방법

공유 Lock과 배타적 Lock의 잠금은 Auto Commit 이 비활성화 되거나, BEGIN 혹은 START TRANSACTION 명령을 통해 트랜잭션이 시작된 상태에서만 잠금이 유지된다.

  • 공유 Lock (SELECT FOR SHARE)
    아래와 같이 SELECT FOR SHARE 를 사용하여 특정 데이터로부터 공유 Lock을 획득할 수 있다.
SELECT * FROM table_name WHERE id = 1 FOR SHARE;
  • 배타적 Lock (SELECT FOR UPDATE)
    아래와 같이 SELECT FOR UPDATE 를 사용하여 특정 데이터로부터 배타적 Lock을 획득할 수 있다.
SELECT * FROM table_name WHERE id = 1 FOR UPDATE;

잠금 없는 읽기

InnoDB 스토리지 엔진을 사용하는 테이블에서 FOR UPDATE 혹은 FOR SHARE 절을 가지지 않는 SELECT 쿼리는 잠금 없는 읽기가 지원된다. 따라서 특정 데이터가 FOR UPDATE 로 락이 걸린 상태라도 FOR UPDATE , FOR SHARE 가 없는 단순 SELECT 쿼리는 아무런 대기 없이 해당 데이터를 조회할 수 있다.

데드락(DeadLock)

DB 데드락이란 두 개 이상의 트랜잭션이 서로 상대방이 가지고 있는 자원을 기다리면서 무한정 대기하는 현상을 말합니다.

예를 들어, 트랜잭션 A가 테이블 X의 레코드를 잠근 상태에서 테이블 Y의 레코드를 요청하고, 트랜잭션 B가 테이블 Y의 레코드를 잠근 상태에서 테이블 X의 레코드를 요청하면, 두 트랜잭션은 서로가 잠근 자원을 해제할 때까지 기다리게 됩니다.

해결 방법

DB 데드락을 방지하거나 해결하기 위한 방법은 여러 가지가 있습니다. 대표적인 방법은 다음과 같습니다.

  • 타임아웃 설정
    트랜잭션이 일정 시간 동안 자원을 기다리다가 타임아웃이 발생하면, 트랜잭션을 롤백하고 다시 시도합니다. 이 방법은 간단하지만, 자주 발생하는 데드락에는 적합하지 않습니다.

  • 자원 순서 부여
    트랜잭션이 요청하는 자원에 순서를 부여하고, 트랜잭션은 순서대로 자원을 요청하도록 합니다.
    예를 들어, 테이블 X와 Y에 1과 2의 순서를 부여하고, 트랜잭션은 1부터 2까지의 순서로만 자원을 요청하도록 합니다. 이 방법은 데드락을 완전히 방지할 수 있지만, 자원의 활용도가 낮아질 수 있습니다.

  • 데드락 감지 및 복구
    DBMS가 데드락을 감지하는 알고리즘을 실행하고, 데드락이 발생하면 특정 트랜잭션을 선택하여 롤백하고 다시 시도합니다. 이 방법은 데드락이 발생한 후에 해결하기 때문에, 성능 저하가 발생할 수 있습니다.

참고

Geeksforgeeks.org
mysql

post-custom-banner

0개의 댓글