DB

DB Lock

Jay-JI 2024. 7. 10. 19:45

이번 포스트를 보기 앞서 이전 포스트를 보고 오시기 바랍니다.

 

https://jaystorage.tistory.com/29

 

Transaction의 Isolation Level

이번 포스트를 보기 앞서 이전 포스트를 보고 오시기 바랍니다.https://jaystorage.tistory.com/28 DB TransactionTransaction 이란? 트랜잭션은 데이터베이스의 상태를 변환시키는 하나의 논리적 기능을 수행

jaystorage.tistory.com

 


 

DB Lock 이란?

 

DB Lock이란 데이터베이스에서 동시성과 데이터 일관성을 보장하기 위해 사용되는 메커니즘을 의미한다. 이러한 DB Lock은 여러 트랜잭션이 동시에 데이터에 접근하더라도 데이터가 손상되거나 일관성이 깨지지 않도록 만들어준다.

 

참고로 DB Lock은 업체 마다 Lock의 종류와 전략이 조금씩 차이가 있다. 아래 내용은 InnoDB를 기준으로 작성한 내용이다.

 

DB Lock 종류

 

 

공유 Lock (Shared Lock / S-Lock)

  • Read에 대한 Lock(데이터를 읽는 작업을 위한 Lock)
  • 일반적인 SELECT 쿼리가 아닌 SELECT … LOCK IN SHARE MODE 또는 SELECT … FOR SHARE 와 같은 쿼리를 사용할 때 각 row에 걸리는 Lock
  • 해당 row에 S-Lock이 걸려 있으면 다른 트랜잭션이 S-Lock은 걸 수 있으나 X-Lock은 걸 수 없다.

 

배타 Lock (Exclusive Lock / X-Lock)

  • Write에 대한 Lock (데이터 변경하는 작업을 위한 Lock)
  • UPDATE, DELETE 혹은 SELECT … FOR UPDATE 쿼리를 사용할 때 각 row에 걸리는 Lock
  • 해당 row에 X-Lock이 걸려 있으면 다른 트랜잭션은 S-Lock, X-Lock 둘 다 걸 수 없다.

 

Record Lock

  • InnoDB의 Record Lock은 row가 아닌 DB index record에 걸리는 Lock
  • 만약 테이블에 index가 없다면 숨겨져 있는 Clustered index를 사용하여 record를 잠금
  • 위에서 설명한 S-Lock, X-Lock 은 일반적으로는 테이블 row를 대상으로 하지만 InnoDB 에서는 독특하게 DB index record를 대상으로 동작함
  • 이것이 가능한 이유는 InnoDB의 정책이 다음과 같기 때문
- 테이블 생성 시 PK를 정의하면 InnoDB는 PK로 Clustered Index를 사용한다.
- PK로 사용할 만한 Unique 하고 Not Null인 컬럼, 혹은 컬럼의 Set이 없다면 자동 증가 컬럼을 추가하는 식으로 Clustered Index를 구성한다.
- 테이블에 PK가 없고 적절한 Unique Index도 없는 경우에는 Row ID 값을 포함하여 만든 컬럼으로 Hidden Clustered Index를 생성하여 사용한다.

* 즉 InnoDB 테이블에는 기본적으로 Clustered Index가 반드시 존재한다.

 

 

Gap Lock

  • index record의 gap에 걸리는 Lock
  • gap이란 index record가 없는 부분
  • 조건에 해당하는 새로운 row가 추가되는 것을 방지하기 위한 것

 

Blocking

 

블로킹은 Lock 간의 경합이 발생해서 특정 트랜잭션이 작업을 진행하지 못하고 대기하는 상태를 의미한다. 

블로킹은 다음과 같은 상황에 발생한다.

[예시]

1) 특정 데이터에 공유 Lock(S-Lock)이 설정된 상태에서 해당 데이터에 배타 Lock(X-Lock)을 설정하려고 할 때
2) 특정 데이터에 배타 Lock(X-Lock)이 설정된 상태에서 해당 데이터에 공유 Lock(S-Lock)을 설정하려고 할 때
3) 특정 데이터에 배타 Lock(X-Lock)이 설정된 상태에서 해당 데이터에 배타 Lock(X-Lock)을 설정하려고 할 때

 

 

이러한 블로킹을 방지하는 방법은 다음과 같다.

 

  1. Transaction을 가능한 한 짧게 유지하기
    - 트랜잭션이 짧을수록 다른 트랜잭션이 대기하는 시간이 줄어든다.

  2. 적절한 index 사용
    - 적절한 인덱스를 사용하면 데이터 검색 및 수정 작업의 성능이 향상되어 Lock이 걸리는 시간을 줄일 수 있다.
    - 인덱스를 효율적으로 사용하면 특정 row에 신속하게 접근할 수 있다.

  3. Lock의 범위 최소화
    - 가능한 한 작은 범위의 row를 대상으로 Lock을 사용한다.

  4. Lock 타임아웃 설정
    - 일정 시간 이후에 Lock을 해제하도록 하면 무한 대기 상태를 방지할 수 있다.

 

Dead Lock

 

데드락은 두 트랜잭션 모두가 블로킹 상태에 진입하여 서로의 블로킹을 해결할 수 없는 상태를 의미한다.

[예시]

1) 세션 A에서 Coupon 데이터에 X-Lock 설정 & 세션 B에서 Member 데이터에 X-Lock 설정
2) 세션 A에서 X-Lock 설정이 되어있는 Member 데이터에 S-Lock을 설정
3) Member 데이터에는 이미 X-Lock 설정이 되어 있으므로 트랜잭션 A는 블로킹 상태 진입
4) 세션 B에서도 X-Lock 설정이 되어 있는 Coupon 데이터에 S-Lock 설정
5) Coupon 데이터에는 이미 X-Lock 설정이 되어 있으므로 트랜잭션 B는 블로킹 상태 진입
6) 트랜잭션 A, B의 블로킹 상태는 상대 트랜잭션이 종료되어야 해결되는데 서로의 트랜잭션이 블로킹 상태이기 때문에 종료되지 않으므로 데드락 상태가 됨

 

 

[MySQL에서 Dead Lock을 해결하는 방법]

  1. deadlock detection
    - dead lock 발생시 작은 트랜잭션을 선택 후 롤백
    - 트랜잭션의 크기는 insert, update, delete 된 row 수에 의해 결정

  2. lock wait timeout
    - 일정 시간이 지나면 time out 에러 발생

출처 : 
https://www.youtube.com/watch?v=onBpJRDSZGA
https://ksh-coding.tistory.com/121
https://jh-labs.tistory.com/407
https://blog.ex-em.com/1699