우디의 개발스터디

[Database] Lock 이란

by 개발자 우디

얼마전 업무 중 DB 락이 걸려서 잠시 애를 먹은적이 있다. 다행히 구글링을 통해 락이 걸린 프로세스들을 찾아 금방 해결할 수 있었지만 LOCK 이 정확히 어떤건지 알고 넘어가는게 좋을 것 같다는 생각이 들었다.

 

락 해제 방법

https://coding-plant.tistory.com/148

 

[PostgreSQL] 테이블 Lock 조회 및 Kill 방법

현재 수행중인 SQL 전체 조회 select datname, pid, usename, application_name, client_addr, client_port, backend_start, query_start, wait_event_type, state, backend_xmin query from pg_stat_activity..

coding-plant.tistory.com

 

DB Lock 이란

데이터의 일관성을 보장하기 위한 방법이다.

 

DB에서 데이터 수정은 DB Lock을 가진 세션만 가능하다. 데이터를 수정하기 위해 접근하면, 세션은 DB Lock을 얻을 수 있는지 확인하고 가능하다면 바로 획득한다. 그리고 트랜잭션이 Commit 될 때, DB Lock을 반납한다.

 

DB Lock이 필요한 이유

예를 들어 두 개의 DB 세션이 존재한다고 가정해보자. 세션 1이 A라는 행의 데이터를 수정중이고 이를 아직 커밋하지 않은 상황이다. 이 때, 세션2가 A라는 행에 접근해서 데이터를 수정하는 상황이 있다고 가정해보자. 한 마디로 설명하면, A라는 곳을 동시에 여러 세션이 수정하려고 하는 상황이다. 이러한 과정은 데이터의 정합성과 원자성을 무너뜨리기 떄문에 문제가 야기될수 있다.

 

과정으로 보자면 세션1은 A → B → C 순으로 접근해서 각각의 데이터를 수정하는 일을 한다고 가정한다. 세션1이 A의 값을 수정하고, B의 값을 수정하는 순간 세션2가 A의 값을 다시 수정한다고 가정해보자. 그리고 세션1이 C의 값을 수정하는 순간 문제가 발생해서 세션1의 트랜잭션이 롤백된다고 가정해보자.

 

그렇다면 이 때, 'A'의 값은 어떤 값으로 롤백 되는 것이 맞을까? 트랜잭션이 시작되기 전 지점으로 돌아가는 것이 맞을까? 아니면 세션2가 수정한 값으로 변경한 값이 맞을까? 다양한 경우의 수가 존재하게 될 것이다.

 

이처럼 여러 세션이 동시에 동일한 곳에 접근해서 데이터를 수정하는 경우, 데이터의 정합성에 대한 신뢰도 문제가 발생한다. 따라서 한 세션이 데이터를 수정중인 경우 다른 세션은 데이터를 수정하지 못하게 하는 것이 바람직하다. 이 때 사용하는 것이 DB Lock이다.

 

Lock의 종류는

Lock은 크게 두 종류로 구분한다.

1. Shared Lock(공유 Lock 또는 Read Lock)
보통 데이터를 읽을 때 사용한다. 원하는 데이터에 Lock을 걸었지만 다른 세션에서 읽을 수 있고, 공유Lock을 설정한 경우 추가로 공유Lock을 설정할 수 있지만, 배타적 Lock은 설정할 수 없다.

즉, 내가 보고 있는 데이터는 다른 사용자가 볼 수 있지만, 변경할 수는 없는 상태

2. Exclusive Lock(배타적 Lock 또는 Write lock)
보통 데이터를 변경할 때 사용한다. 이름에서 보여지듯이 해당 Lock이 해제되기 전까지는, 다른 공유Lock, 배타적Lock을 설정할 수 없다.

즉, 읽기와 쓰기가 불가능한 상태

 

Blocking

블로킹은 Lock들의 경합(==Race condition)이 발생하여 특정 세션이 작업을 진행하지 못하고 멈춰 선 상태를 의미한다. (공유Lock과 배타적Lock) 또는 (배타적Lock과 배타적Lock)끼리 블로킹이 발생할 수 있다. 이를 해결하는 방법은 Transaction commit 또는 rollback 으로 제어하는 방법뿐이다.

경합이 발생할 때, 먼저 Lock을 설정한 트랜잭션을 기다려야하기 때문에, 이런 현상이 반복되면 사용자에게 양질의 서비스를 제공하기가 어려워진다.

블로킹 해결 방법

  1. 트랜잭션을 가능한 짧게 정의하면 경합을 줄일 수 있다.
  2. 동일한 데이터를 동시에 변경하는 작업을 하지 않도록 설계하는 것이 좋다.
  3. 트랜잭션이 활발한 주간에는 대용량 갱신 작업을 수행하면 안됨.
  4. 대용량작업이 불가피할 경우, 작업단위를 쪼개거나 lock_timeout을 설정하여 해당 Lock의 최대시간을 설정할 수 있다.
-- 예시
set lock_timeout 3000

 

Dead Lock

DeadLock은 트랜잭션간의 교착상태를 의미한다. 두 개의 트랜잭션간에 각 트랜잭션이 가지고 있는 리소스의 Lock을 획득하려고 할 때 발생하는 교착상태이다.

DeadLock 예시

 

위 사진은 가장 흔히 떠올릴 수 있는 deadlock 상황이다. 좌측 1번 트랜잭션에서 우측 2번 리소스의 잠금을 획득, 2번 트랜잭션에서는 1번 리소스의 잠금을 획득한 상태이다. 이 때, 동시에 상대방의 데이터를 엑세스하려고 할때 기존의 Lock이 해제될 때까지 기다리게 되는 교착상태에 빠지게 된다.

 

DeadLock 예시2

 

두번째 예시는, 1번 트랜잭션이 공유Lock을 설정하고 Sleep에 빠져버렸을 때를 보여준다. 이때 2번 트랜잭션은 배타적Lock을 설정하려고 시도하여도, 계속 기다리게만 되는 교착상태에 빠지게 된다.

참고로 내가 업무에서 주로 사용하는 Postgresql 에서는 자동적으로 deadlock을 인지하고 교착상태를 해결하기 위하여 하나의 트랜잭션을 취소시켜준다. 하지만 정확히 어떤 트랜잭션이 취소될 지 판단하는게 불가능하다.

 

쉽게말하면

 

TIP
 
 

둘 이상의 프로세스가 특정 자원을 얻지 못해서 다음 명령을 처리 못하는 상태 (교착상태) 한정된 자원을 여러 곳에서 사용하려고 할 때 발생

 

참고

http://www.sqler.com/320577

 

개발자 커뮤니티 SQLER.com - 교착상태 (DeadLock)

교착상태(DeadLock)은 서로 다른 두개의 작업(트랜잭션)이 리소스 잠금을 교차해서 획득하려 할 때 발생합니다. 가장 보편적인 DeadLock그림입니다. T1작업은 R1(리소스)의 잠금을 획득하고 R2를 액세

www.sqler.com

https://ojt90902.tistory.com/856

 

Spring DB : DB 락 - 개념 이해

이 글은 인프런 김영한님의 강의를 복습하며 작성한 글입니다. DataBase Lock의 개념 이해 두 개의 DB 세션이 존재한다고 가정해보자. 세션 1이 A라는 행의 데이터를 수정중이고 이를 아직 커밋하지

ojt90902.tistory.com

 

블로그의 정보

우디의 개발스터디

개발자 우디

활동하기