[DB] Transaction Concurrency control (동시성 제어)

0
post-custom-banner

Concurrency control

  • 트랜잭션이 동시에 수행 될 때, 일관성을 해치지 않도록 트랜잭션의 데이터 접근을 제어하는 DBMS의 기능을 동시성 제어(Concurrency control)이라고 한다.

동시성 제어 시나리오

상황트랜잭션1트랜잭션2
상황1읽기읽기
상황2읽기쓰기
상황3쓰기쓰기

읽기만 한다면 크게 문제가 없지만 문제는 상황2, 상황3에서 나타난다.
상황2는 Isoltion level에서 다루고 동시성 제어에서는 상황3을 살펴보자

갱신손실 문제

갱신손실(lost update) 문제는 두 개의 트랜잭션이 한 개의 데이터를동시에 갱신할 때 발생한다.

작업 설명

  1. T1(트랜잭션1)은 예금을 인출하는 작업
  2. T2(트랜잭션2)는 입금하는 작업
  3. T1은 계좌 X에서 100을 뺀다.
  4. T2는 계좌 X에 100을 더한다.
  5. X에 기본 1000값이 있다고 가정한다.

시나리오 : 두 개의 트랜잭션이 동시에 작업을 진행

T1T2버퍼 값Index
A = read_item(X);
A = A - 100
-X = 10001
-B = read_item(X);
B = B + 100
X = 10002
write_item(A -> X);-X = 9003
-write_item(B -> X);X = 11004

일관성이 깨진 것을 알 수 있다.
원인은 Index2에서 X 값을 읽어온 T2는 T1이 갱신을 준비 중인 데이터를 읽어와 작업을 진행한다.
그리고 Index3 에서 T1이 기록한 데이터를 무시하고 다시 한 번 끼어들어 Index4에서 X 값을 갱신한다.

해결

갱신손실 문제를 해결하려면 상대방의 트랜잭션이 데이터를 사용하는지 여부를 알 수 있는 규칙이 필요하다. 즉, 자신이 데이터를 수정 중이라는 사실을 알리면 된다.
알리는 방식으로 락(Lock)이라는 잠금장치를 사용한다.

Lock

락은 자신이 사용할 데이터를 잠그면 다른 트랜잭션은 잠금이 풀릴 때까지 wait 해야한다.
이로써 X에 대한 갱신을 순차적으로 진행할 수 있고, 갱신손실 문제를 해결할 수 있다.

시나리오 : Use Locking

T1T2버퍼 값Index
LOCK(X) A = read_item(X);
A = A - 100
-X = 10001
-LOCK(X)
(wait... 대기)
X = 10002
write_item(A -> X);
UNLOCK(X);
-X = 9003
-B = read_item(X);
B = B + 100
write_item(B -> X);
UNLOCK(X);
X = 11004

작업설명 : 하나의 데이터에 두 트랜잭션을 접근하여 갱신하는 작업

T1T2
START TRANSACTION;
USE DB_NAME

SELECT
FROM Book
WHERE bookid = 1;

UPDATE Book
SET price = 7100
WHERE bookid = 1;

SELECT

FROM Book
WHERE bookid = 1;

COMMIT;
START TRANSACTION;
USE DB_NAME

SELECT
FROM Book
WHERE bookid = 1;

UPDATE Book
SET price = price + 100
WHERE bookid = 1;

SELECT

FROM Book
WHERE bookid = 1;

COMMIT;

데드락

두 개 이상의 트랜잭션이 각각 자신의 데이터에 대해 락을 획득하고 상대방 데이터에 대해 락을 요청하면 무한 대기 상태에 빠진다.
이러한 현상을 데드락 or 교착상태 라고 한다.

데드락 해결

데드락이 발생하면 일반적으로 작업중인 트랜잭션 중 하나를 강제 중지 시킨다. 그 결과 나머지 트랜잭션은 정상적으로 실행된다. 이 때 중지시키는 트랜잭션에서 변경한 데이터는 원래 상태로 rollback한다.

profile
즐겁게 코딩하는 하루 🌇🌆
post-custom-banner

0개의 댓글