데이터베이스

[DB] 데이터베이스 락(Locking) & 동시성 제어

위시리 2025. 4. 7. 01:04

데이터베이스에서 Lock은 여러 트랜잭션(데이터베이스 작업 단위)이 동시에 데이터에 접근하고 수정하는 상황에서 데이터의 일관성과 무결성을 보장하기 위해 사용되는 개념

 

DB Lock의 Level
  1. 행 수준 잠금(Row-level Locking) : 데이터를 개별 행 단위로 잠금을 설정하는 것을 말한다. 이 경우에는 특정 행만 잠겨서 다른 트랜잭션은 해당 행에 접근할 수 없게 된다.
  2. 테이블 수준 잠금(Table-Level Locking) :  테이블과 인덱스에 모두 잠금을 설정. Select table, Alter table, Vacuum, Refresh,Index, Drop, Truncate 등의 작업에서 해당 레벨의 락이 설정된다.
  3. 데이터베이스 수준 잠금(Database-Level Locking) : 데이터베이스를 복구하거나 스키마를 변경할 때 발생

 

🔐 1. Global Lock

MySQL 인스턴스(서버) 전체에 영향을 주는 락

  • FLUSH TABLES WITH READ LOCK (FTWRL) 명령으로 획득할 수 있다.
  • SELECT 쿼리를 제외한 대부분의 DDL이나 DML 쿼리를 실행할 수 없다.
  • 데이터 베이스의 구조적 변경, 백업 수행  또는 크리티컬한 데이터 마이그레이션 작업 시에 사용된다.
  • 그 중 백업 시 자주 사용되며, 모든 테이블에 대한 읽기 락을 걸어 새로운 쓰기 작업을 차단한다. 이 락이 걸린 동안에는 DML(insert, update 등) 작업이 차단되며, 읽기만 가능하다.
데이터 마이그레이션 (Data Migration)

한 시스템에서 다른 시스템으로 데이터를 이전하는 과정
보통 시스템 교체, 업그레이드, 통합, 클라우드 이전 등 다양한 이유로 수행된다.

 

Backup Lock

  • LOCK INSTANCE FOR BACKUP
  • MySQL이 8.0부터 InnoDB가 기본 Storage 엔진이 되면서 조금 더 가벼운 글로벌 락의 필요성이 생겼다.
  • 논리적 백업 대신 물리적 백업을 위해 사용되는 락으로, FTWRL 과 달리 InnoDB의 내부 기능과 통합되어 세분화된 백업 시점 제어가 가능하다.
  • InnoDB는 트랜잭션을 지원하기 때문에 일관된 데이터 상태를 위해 모든 데이터의 변경 작업을 멈출 필요가 없어졌다.
    • 이러한 이유로 Backup Lock이 도입
LOCK INSTACE FOR BACKUP
-- // 백업 실행
UNLOCK INSTANCE
  • 백업 락은 일반적인 테이블의 데이터 변경은 허용되고 스키마 변경 같은 DDL 명령어가 실행되면 복제를 일시 중지하는 역할을 한다.

 

(2. Database Lock)

  • MySQL에서는 명시적인 데이터베이스 단위 락은 존재하지 않지만, 논리적인 분류로 이해하는 경우가 많다.
  • 예를 들어, 어떤 관리 작업(DDL)이 특정 DB의 여러 테이블에 동시에 영향을 미친다면, 전체 DB 수준의 영향을 줄 수는 있다.
  • 하지만 실제 락 수준은 테이블 락이나 MDL로 구현된다.

 

🔐 3. Table Lock

  • 전체 테이블에 대한 잠금으로 특정 테이블의 모든 행에 대한 잠금을 설정한다.
  • 주로 대량의 데이터를 추가, 업데이트 또는 삭제하는 배치 작업에서 유리하며, 이러한 작업 중에는 다른 작업의 간섭을 최소화할 필요가 있다.
LOCK TABLES table_name [AS alias] {READ | [READ LOCAL] | WRITE}
  • (명시적) 명령으로 특정 테이블의 락을 획득할 수 있으며 MyISAM 뿐만 아니라 InnoDB에서도 사용이 가능하며 명시적으로 획득한 잠금은 UNLOCK TABLES 명령으로 잠금을 반납할 수 있다.
  • (묵시적) 묵시적인 테이블 락은 스키마를 변경하는 쿼리(DDL)을 사용하는 경우에 발생하며, 이 경우에는 쿼리가 완료된 후 자동으로 락이 해제된다.

 

Intention Lock

  • MySQL InnoDB 엔진에는 intention lock의 개념도 존재
  • row에 대해서 나중에 어떤 row-level 락을 걸 것을 알려주기 위해 미리 table-level에 걸어두는 lock
  • Intention Lock은 Row Lock이 아니다! → 트랜잭션이 이 테이블의 어떤 행에 락을 걸려고 하니 알아두라는 선언적 의미
  • Intention Shared Lock (IS)
    • SELECT ... LOCK IN SHARED MODE 가 실행되면
      1. Intention Shared Lock이 테이블에 걸림
      2. row-level 에 S-lock이 걸림
  • Intention Exclusive Lock (IX) 
    • SELECT ... FOR UPDATE, INSERT, DELETE, UPDATE 이 실행되면
      1. Intention Exclusive Lock 이 테이블에 걸림
      2. row-level 에 X-Lock 이 걸림

 

🔐 4. Row Level Lock

  • InnoDB 스토리지 엔진에서 제공하는 가장 세분화된 락 수준
  • 트랜잭션 처리 시 특정 행 단위에 대한 락으로 동시성이 높은 환경에서 유리
  • 행 단위로 잠금을 관리함으로 여러 트랜잭션이 서로 다른 행을 동시에 처리 가능

4-1. Shared Lock (S Lock, 공유 락)

  • 데이터를 읽을 때 사용하는 Lock
  • SELECT ... LOCK IN SHARE MODE 등의 쿼리에서 사용
  • 하나의 트랜잭션이 데이터를 읽고 있는 경우, 다른 트랜잭션들도 해당 데이터를 읽을 수는 있지만 쓰기 작업은 금지된다.
  • 데이터의 일관성을 유지할 수 있다.
  • 트랜잭션 격리수준 중 Repeatable Read 단계와 연관

4-2. Exclusive Lock (X Lock, 배타 락)

  • 데이터를 변경하고자 할 때 사용되며, 트랜잭션이 완료될 때까지 유지된다.
  • UPDATE, DELETE 등에서 자동으로 사용되며, 다른 트랜잭션이 해당 행에 접근하지 못하도록 완전히 잠근다.
  • (특정 트랜잭션이 데이터를 수정하고 있는 경우, 해당 데이터에 대한 다른 모든 트랜잭션의 접근이 금지된다.)
  • 트랜잭션 격리 수준 중 Serializable 단계와 연관

 

 

row-level 및 table-level 에서 두 번 Lock 을 하는 이유
  • A 트랜잭션에서 이미 테이블에 대해 락이 걸려있는데, B 트랜잭션에서 해당 테이블의 특정 row에 대한 lock을 거는 것을 원천적으로 방지할 수 있다. (반대의 경우도 마찬가지)
  • EX) row-level의 write이 일어나고 있을 때, 테이블 스키마가 변경되서는 안된다. write query의 경우 이미 IX 락을 획득한 상태이기 때문에 해당 테이블의 스키마가 변경되는 것을 막을 수 있다.

🔒 테이블 락 모드 호환성 (Lock Compatibility Matrix)

  X (Exclusive)  IX (Intent Exclusive) S (Shared) IS (Intent Shared)
X Conflict Conflict Conflict Conflict
IX Conflict Compatible Conflict Compatible
S Conflict Conflict Compatible Compatible
IS Conflict Compatible Compatible Compatible
  • Conflict: 락을 걸 수 없음 (기존 락과 충돌)
  • Compatible: 락을 걸 수 있음 (동시에 존재 가능)


부연 설명

  • 예시:
    row-level의 write(예: UPDATE, INSERT)가 발생할 경우, 이미 해당 row에 대해 IX 락이 걸린 상태이기 때문에, 이 시점에서 테이블 스키마 변경(X 락 필요)은 Conflict로 인해 허용되지 않는다.
  • 의미 요약:
    락 호환성은 동시 작업의 안전성과 정합성을 보장하기 위한 메커니즘이다. IX 락은 의도된 하위 레벨의 락(예: row-level exclusive)에 대한 신호이며, X 락은 전체 자원에 대한 독점 락을 의미하므로, IX가 존재하면 X 락은 충돌하게 된다.

 

Escalation

  • 잠금 수준을 최적화하는 과정
    • Lock Escalation 은 데이터베이스 시스템이 특정 Lock Level에서 다른 Lock Level로 전환하는 과정을 의미한다.
    • 일반적으로 특정 트랜잭션에서 많은 수의 잠금을 설정하려는 경우 시스템은 이를 관리하기 위해 Lock Level을 높일 수 있다.
  • Lock 레벨이 낮을 수록 동시성이 좋아지지만, 관리해야할 Lock이 많아지기 때문에 메모리 효율성은 떨어진다.
    • 반대로 Lock 레벨이 높을 수록 관리 리소스는 낮지만, 동시성은 떨어진다.

 

 

Blocking (블로킹)
  • Lock 간의 경합(Race Condition)이 발생하여 특정 Transition이 작업을 진행하지 못하고 대기하는 상태
  • 공유 락끼리는 블로킹이 발생하지 않지만 베타 락은 블로킹을 발생시킨다.
    • 특정 데이터에 공유 Lock이 설정된 상태에서 해당 데이터에 배타 Lock을 설정하려고 할 때
    • 특정 데이터에 배타 Lock이 설정된 상태에서 해당 데이터에 공유 Lock을 설정하려고 할 때
  • 블로킹을 해소하기 위해서는 이전 트랜잭션이 완료 (commit / rollback)이 되어야 한다.

https://ksh-coding.tistory.com/121

  • 위 그림에서 Coupon 데이터에 트랜잭션 A가 S-Lock을 설정한 후에 트랜잭션 B가 X-Lock을 설정하여 트랜잭션 B가 블로킹 상태에 진입한 것을 알 수 있다.
  • 트랜잭션 A:
    SELECT ... FOR SHARE 실행 → S-Lock (공유 락) 획득
    → 읽기 전용으로 id=1인 행을 보고 있음 (변경은 안 함)

  • 트랜잭션 B:
    SELECT ... FOR UPDATE 실행 → X-Lock (배타 락)을 걸려고 시도
    → 하지만 이미 A가 S-Lock을 걸고 있어서 X-Lock을 획득할 수 없음

🔒 왜 Block 되는가?

  • S-Lock과 X-Lock은 서로 호환되지 않음
    → S-Lock은 읽기 전용이고, X-Lock은 쓰기 및 수정을 하기 위한 락이기 때문
  • A가 S-Lock을 걸고 있는 동안에는:
    • 다른 트랜잭션이 또 다른 S-Lock은 가능
    • 하지만 X-Lock은 불가능 (쓰기 금지)
  • 그래서 트랜잭션 B는 A가 트랜잭션을 커밋하고 락을 해제할 때까지 기다려야 함

💡 핵심 포인트

  • 공유 락(S-Lock) → 읽기 전용, 서로 겹쳐도 OK
  • 배타 락(X-Lock) → 쓰기, 다른 어떤 락과도 겹치면 안 됨
  • 그래서 트랜잭션 A가 끝나기 전까지 B는 블로킹 당하는 거고, 이것이 락 충돌로 인한 트랜잭션 대기 상황이다.

 

해결 방법

  1. SQL 문의 리팩토링
  2. 트랜잭션을 가능한 짧게 정의
  3. 동일한 데이터를 동시에 변경하는 작업을 하지 않도록 설계
  4. 대용량 작업이 불가피한 경우, 작업 단위를 쪼개거나 lock_timeout을 설정

 

 

Dead Lcok (데드락, 교착상태)

https://kamja-ming.tistory.com/entry/DB-%EB%9D%BDLock%EC%9D%B4%EB%9E%80

 

  • 두 개의 트랜잭션 간의 각각의 트랜잭션이 가지고 있는 리소스의 Lock을 획득하려고 할 때 발생
  • 각각의 트랜잭션에 Lock을 걸고 상대방 Lock에 접근하여 반환 받지 못하는 상황에서
  • 서로 상대방의 락이 풀리기를 기다리는데, 그 락을 각자 상대가 들고 있어서 영원히 진행되지 않는 Dead Lock 이 발생하게 된다.

 

해결 방법

  1. Dead Lock 이 감지되면 둘 중 하나의 트랜잭션을 강제 종료한다.
    • 실제로, Oracle 에서는 데드락이 감지되면 한쪽 Transaction을 강제로 풀어버린다.
    • 이렇게 되면 하나의 트랜잭션 A의 마지막 실행 내용에 오류가 발생되고 커밋이 발생되도록 유지한다.
    • 또 다른 트랜잭션 B는 아직 대기 중이며, 트랜잭션 A의 커밋을 기다린다.
  2. Dead Lock 방지를 위해 접근 순서를 동일하게 하는 것이 중요하다. → 접근 순서 규칙을 정한다.

 

 

🔸 Blocking vs DeadLock

구분 블로킹 (Blocking) 데드락 (Deadlock)
정의 한 트랜잭션이 다른 트랜잭션의 락 해제를 기다리는 상태 둘 이상의 트랜잭션이 서로의 락을 기다리며 무한 대기에 빠지는 상태
대기 구조 단방향 대기 (한 쪽이 기다림) 순환 대기 (A → B → A 형태로 서로 기다림)
지속 여부 선행 트랜잭션이 커밋/롤백되면 해소됨 양쪽 다 기다리기 때문에 외부 개입 없이는 해소되지 않음
발생 조건 일반적인 트랜잭션 상황에서 자주 발생 가능 네 가지 조건이 충족될 때만 발생 (자원 점유, 대기, 비선점, 순환 대기)
해결 방법 기다리면 됨 (락 해제되면 진행됨) DBMS가 감지해서 트랜잭션 중 하나를 강제 종료(rollback)

 

💡 Ex - Blocking (블로킹)

  1. 트랜잭션 A가 row에 S-Lock을 걸고 읽는 중
  2. 트랜잭션 B가 동일 row에 X-Lock을 걸려고 시도
    → A가 끝날 때까지 B는 기다림 → 이것이 블로킹

💡 Ex - Deadlock (데드락)

  1. 트랜잭션 A가 row 1에 락을 걸고, row 2의 락을 요청
  2. 동시에 트랜잭션 B가 row 2에 락을 걸고, row 1의 락을 요청
    → A는 B가 가진 락을 기다리고, B는 A가 가진 락을 기다림
    → 서로 영원히 기다리는 상태 → Deadlock

 

블로킹은 일시적인 기다림, 데드락은 서로 영원히 기다리는 교착 상태

 

 

Optimistic Lock (낙관적 락)과 Pessimistic Lock (비관적 락)

낙관적 락 : "먼저 처리하고, 나중에 확인"
비관적 락 : "먼저 잠그고, 나만 처리"

 

Optimistic Lock

  • 데이터 갱신 시 충돌이 발생하지 않을 것으로 간주하는 방식
  • 데이터를 읽을 때 잠금을 설정하지 않고, 데이터를 변경하기 전에 충돌을 검출하는 방식이다.
  • 주로 데이터 충돌이 적은 상황에서 사용

 

Pessimistic Lock

  • 데이터 갱신 시 충돌이 발생할 것으로 보고 미리 잠금을 하는 방식
  • 데이터를 읽을 때나 변경할 때 바로 잠금을 설정하여 다른 트랜잭션의 접근을 막는 방식이다.
  • 무결성에 장점이 있지만 데드락의 위험성이 존재한다.

 

구분 낙관적 락 (Optimistic Locking)  비관적 락 (Pessimistic Locking)
개념 충돌이 드물다고 가정하고, 데이터에 락을 걸지 않음 충돌이 자주 발생한다고 가정하고, 미리 락을 설정함
락 방식 실제 수정 시점에 버전 체크 데이터 접근(읽기/쓰기) 시점에 락을 설정
충돌 처리 충돌 시 예외 처리 및 재시도 충돌 자체를 차단하여 동시성 문제를 방지
사용 방식 버전 번호 또는 타임스탬프를 이용해 변경 확인
JPA 사용시 @Version
DB 수준의 SELECT ... FOR UPDATE 같은 명령 사용
Mode 설정 및 쿼리에 직접 사용, 
성능 충돌이 적으면 성능 우수 다중 사용자 환경에서 락 경합 발생 시 성능 저하 가능
적합한 상황 읽기 위주, 충돌이 드문 시스템 (예: 게시판, 통계 등) 동시 업데이트 가능성이 높은 환경 (예: 은행 거래 등)
장점 데드락 가능성이 적으며  성능의 이점 충돌에 대한 오버헤드가 줄어들며 무결성을 지키기 용이
단점 충돌이 발생하면 오버헤드 발생 충돌이 없으면 오버헤드가 발생
예시 버전 필드 비교 후 UPDATE 트랜잭션 내 SELECT ... FOR UPDATE 사용

 

낙관적 락  / 비관적 락 vs 공유 락 / 배타적 락

  • 낙관적 락과 비관적 락은 데이터 충돌의 빈도와 대응 방식을 나타내며
  • 공유 잠금과 배타적 잠금은 데이터의 읽기와 쓰기 작업 간의 관계를 나타낸다.

 

 

 

Reference

https://kamja-ming.tistory.com/entry/DB-%EB%9D%BDLock%EC%9D%B4%EB%9E%80

 

[DB] 락(Lock)이란?

💡 락(Lock)이란? 데이터베이스는 여러 사용자들이 같은 데이터를 동시에 접근하는 상황에서, 데이터의 무결성과 일관성을 지키기 위해 사용 💡 락(Lock)의 종류 크게는 공유락과 배타적락으로

kamja-ming.tistory.com

https://ksh-coding.tistory.com/121

 

[DB] DB Lock이란? (feat. Lock 종류, 블로킹, 데드락)

0. 락(Lock)이란? 여러 커넥션에서 동시에 동일한 자원을 요청할 경우 순서대로 하나의 커넥션만 변경할 수 있게 해주는 기능 동시성을 제어하기 위한 기능 저는 처음에 DB 락을 접했을 때, 락을 이

ksh-coding.tistory.com