MySQL(DB)

[바미] 트랜잭션 데드락(Transaction DeadLock)

Bami 2023. 9. 25. 15:59
728x90
반응형

Transaction

  • 트랜잭션은 하나의 작업을 수행하는데 필요한 데이터베이스의 연산을 모아놓은 것으로 데이터베이스 작업의 단위라고 생각하면 됩니다.
  • 일반적으로 데이터베이스의 연산은 SQL문으로 이루어져 있으며 트랜잭션을 SQL문의 집합이라고도 합니다.
  • 트랜잭션에서 중요한 것은 트랜잭션 단위로 구분해서 모두 성공하거나 실패해야 데이터베이스의 일관성을 유지할 수 있다는 것입니다. (트랜잭션 특징中)

Transaction Update

트랜잭션에서 UPDATE작업을 할 때 처리과정은 아래와 습니다.

UPDATE TABLE
SET A = 300
WHERE A_ID = 201;

위의 쿼리를 실행하면

  1. 행 레벨 Lock
  2. UNDO SEGMENT Buffer 확보 및 정보 기록
  3. 데이터 UPDATE
  4. COMMIT & 행 Unlock

설명

1. 트랜잭션에서 UPDATE를 할 경우 읽기 일관성을 유지하기 위해 행 레벨에서 Lock을 걸어버립니다.
     다른 트랜잭션에서 Update 작업을 할 수 없도록 막는 작업이죠.

2, 3. 그 후 다른 트랜잭션에서 SELECT를 할 경우 아직 COMMIT을 하지 않았기 때문에 이전 정보를 UNDO BLOCK에서 조회할 수 있도록 정보를 기록해주고 데이터 UPDATE 작업을 진행합니다.

4. Transaction이 최종적으로 끝나면 행 레벨 LOCK을 풀어줍니다.

Lock

대용량의 데이터를 처리하는 데이터베이스 애플리케이션의 경우 데이터의 정확성을 유지하면서 최대한 동시성을 높이는 것이 중요한 포인트입니다.

그렇기 때문에 상황에 따른 여러가지 Lock을 통해 동시성을 제어하며 이를 통해 사용자가 설정한 대로 원하는 수준의 트랜잭션 격리 수준(Transaction Isolation Level)을 유지해주죠.

Lock은 트랜잭션과 비슷한 개념같지만, Lock은 동시성을 제어하기 위한 기능이고, 트랜잭션은 정합성을 보장히기 위한 기능입니다.

데이터의 일관성을 보장하기 위한 하나의 방법인데 오라클과 같이 고가의 DBMS를 사용하는 이유가 데이터의 무결성과 일관성을 유지하기 좋기 때문이죠.

 

Lock은 상황에 따라서 크게 두가지로 나뉩니다.

  1.  Shared Lock(공유 Lock 또는 Read Lock): 데이터를 읽을 때 사용합니다. 내가 보고 있는 데이터는 다른 사용자가 볼 수 있지만, 변경은 불가하죠.
  2. Exclusive Lock(배타적 Lock 또는 Write lock) : 데이터를 변경할 때 사용합니다. 해당 Lock이 해제되기 전까지는, 다른 Lock에 대한 설정을 할 수 없습니다. 읽기 쓰기가 불가능하다는 말입니다.

DeadLock

DeadLock(교착상태)란, 둘 이상의 프로세스가 다른 프로세스가 점유하고 있는 자원을 서로 기다릴 때 무한 대기에 빠지는 상황을 말합니다. 두개의 트랜잭션간에 각각의 트랜잭션이 가지고 있는 리소스의 Lock을 획득하려고 할 때 발생하죠.

DeadLock 발생 원인

하나의 트랜잭션이 테이블A를 업데이트 한 뒤 테이블B를 업데이트 하려고 할 때, 다른 트랜잭션이 이미 테이블B에 업데이트 작업을 진행 중인 경우 해당작업을 완료할 때까지 대기 후 처리하게 되는데 트랜잭션들이 서로 완료 될 때까지 기다리며 결과적으로 무한 대기 상태가 되면 교착상태라고 합니다.

DeadLock의 해결방법

  • 데드락이 발생하지 않도록 예방하기.
  • 데드락 발생 가능성을 인정하면서도 적절하게 회피하기.
  • 데드락 발생을 허용하지만 데드락을 탐지하여, 데드락에서 회복하기.
  • 트랜잭션 진행방향을 같은 방향으로 처리 (테이블A 업데이트 후 테이블B 업데이트, 블로킹).
  • 트랜잭션 처리속도를 최소화.
  • SET LOCK_TIMEOUT: 잠금해제 시간 설정
    • 대용량 작업을 할 때는 작업단위를 쪼개거나 lock_timeout을 설정해서 해당 lock의 최대시간을 설정 할 수 있습니다.
      set lock_timeout 3000

 

참고
https://www.postgresql.org/docs/9.4/explicit-locking.html
https://chanhuiseok.github.io/posts/cs-2/
https://myjamong.tistory.com/181
https://sosopro.tistory.com/55

728x90
반응형