메인 콘텐츠로 건너뛰기

VillageSQL is a drop-in replacement for MySQL with extensions.

All examples on this page work on VillageSQL. Install Now →
교착 상태는 두 트랜잭션이 서로 상대방에게 필요한 잠금을 보유하여 어느 쪽도 진행할 수 없을 때 발생합니다. InnoDB는 이를 자동으로 감지하고 트랜잭션 하나 — “희생자” — 를 ERROR 1213: Deadlock found when trying to get lock; try restarting transaction과 함께 종료합니다.

교착 상태가 발생하는 방식

전형적인 패턴: 두 트랜잭션이 행을 반대 순서로 잠급니다.
InnoDB의 교착 상태 감지기가 순환을 찾아내고, 잠근 자원이 더 적은(또는 더 적은 작업을 수행한) 트랜잭션을 롤백합니다.

교착 상태 로그 읽기

가장 최근의 교착 상태는 InnoDB 상태 출력에서 항상 볼 수 있습니다:
LATEST DETECTED DEADLOCK 절을 찾으세요. 두 트랜잭션, 각각이 보유한 잠금, 기다리던 잠금, 어느 트랜잭션이 롤백되었는지를 보여 줍니다.
추출해야 할 핵심 사항:
  • 어떤 두 쿼리가 충돌하는지
  • 어떤 테이블과 인덱스가 관련되어 있는지
  • 어느 트랜잭션이 희생자(롤백됨)였는지

교착 상태 예방 패턴

일관된 순서로 행 잠그기

위의 교착 상태는 A가 행 1 다음 행 2를 잠그고, B가 행 2 다음 행 1을 잠그기 때문에 발생합니다. 두 트랜잭션이 항상 ID 오름차순으로 잠그면 순환이 형성될 수 없습니다:
애플리케이션 코드를 제어할 수 있다면, 여러 행을 건드리는 작업에 일관된 잠금 순서를 강제하세요.

트랜잭션을 짧게 유지하기

긴 트랜잭션은 잠금을 더 오래 보유하여 충돌이 생길 시간을 더 줍니다. 트랜잭션 안에서는 최소한의 작업만 하세요:

SELECT … FOR UPDATE로 미리 잠그기

트랜잭션이 행을 갱신할 예정이라면, UPDATE에서 잠금 충돌을 발견하기보다 SELECT에서 잠그세요:
이것이 교착 상태를 없애지는 않지만, 잠금 순서를 명시적이고 예측 가능하게 만듭니다.

교착 상태 시 재시도

교착 상태는 동시성 시스템에서 예상되는 일입니다. 올바른 애플리케이션 대응은 ERROR 1213을 잡아 트랜잭션 전체를 재시도하는 것입니다:
개별 문장을 재시도하지 마세요 — InnoDB가 이미 롤백했으므로 트랜잭션 전체를 처음부터 재시도하세요.

갭 잠금과 넥스트 키 잠금

InnoDB는 기본 REPEATABLE READ 격리 수준에서 팬텀 읽기를 막기 위해 갭 잠금과 넥스트 키 잠금을 사용합니다. 이 더 넓은 잠금은 교착 상태 가능성을 높입니다.
READ COMMITTED는 행 잠금만 사용하므로(갭 잠금 없음) 교착 상태 빈도가 줄어듭니다. 트레이드오프는 팬텀 읽기를 허용한다는 것입니다. 대부분의 OLTP 워크로드에서 교착 상태에 민감한 작업에는 READ COMMITTED가 합리적인 선택입니다.

잠금 대기 타임아웃

모든 잠금 충돌이 교착 상태는 아닙니다. 트랜잭션 B가 단순히 A의 잠금을 기다리고 A가 느리다면, B는 innodb_lock_wait_timeout초(기본값: 50) 후에 타임아웃됩니다. 오류는 ERROR 1205: Lock wait timeout exceeded입니다.
타임아웃은 교착 상태가 아닙니다 — InnoDB는 차단하는 트랜잭션을 롤백하지 않았고, 기다리던 트랜잭션만 롤백했습니다.

자주 묻는 질문

현재 모든 잠금과 누가 기다리는지 어떻게 보나요?

data_locks는 현재 보유되거나 요청된 모든 잠금을 보여 줍니다. data_lock_waits는 어떤 스레드가 어떤 스레드를 차단하는지 보여 줍니다.

InnoDB는 항상 교착 상태를 즉시 감지하나요?

InnoDB의 교착 상태 감지기는 잠금 충돌이 발생할 때 동기적으로 실행됩니다. 감지는 거의 즉각적입니다. innodb_deadlock_detect = OFF로 비활성화하고 innodb_lock_wait_timeout에만 의존할 수 있으며, 일부 고동시성 워크로드가 성능을 위해 그렇게 하지만 드문 일입니다.

모든 교착 상태를 예방할 수 있나요?

아니요. 교착 상태는 잠금을 사용하는 동시 트랜잭션의 근본적인 속성입니다. 일관된 잠금 순서와 짧은 트랜잭션으로 빈도를 줄일 수 있으며, 항상 교착 상태에 대한 재시도 로직을 작성해야 합니다.

문제 해결

함께 보기