MariaDB Deadlock 재현과 원인 추적 — 두 세션 잠금 순서로 이해하기

조회수 1

도입

Deadlock은 두 트랜잭션이 서로 상대방의 잠금 해제를 기다리는 순환 대기다. InnoDB는 이를 감지하면 한 트랜잭션을 희생시켜 오류 1213을 반환하고 다른 트랜잭션이 진행하게 한다.

재시도는 피해를 줄일 수 있지만 원인을 설명하지 않는다. 폐기 가능한 MariaDB 10.11 테스트 DB에서 잠금 순서를 재현하고 상태 기록과 쿼리를 함께 확인한다.

Deadlock과 일반 잠금 대기

일반 잠금 대기는 선행 트랜잭션이 끝나면 진행한다. Deadlock은 A가 B를 기다리고 B도 A를 기다려 자연스럽게 풀리지 않는다.

flowchart LR A[세션 A 행 1 잠금] --> B[행 2 대기] C[세션 B 행 2 잠금] --> D[행 1 대기] B --> C D --> A

두 세션으로 잠금 순환 재현하기

두 세션으로 재현하기

CREATE TABLE deadlock_demo (
  id INT PRIMARY KEY,
  amount INT NOT NULL
) ENGINE=InnoDB;
INSERT INTO deadlock_demo VALUES (1, 100), (2, 200);

두 세션에서 START TRANSACTION을 실행한다. A는 ID 1, B는 ID 2를 먼저 갱신한다. A가 ID 2를 기다리는 동안 B가 ID 1을 요청하면 한쪽이 1213 오류로 종료된다.

-- 세션 A
UPDATE deadlock_demo SET amount = amount + 1 WHERE id = 1;
UPDATE deadlock_demo SET amount = amount + 1 WHERE id = 2;

-- 세션 B
UPDATE deadlock_demo SET amount = amount - 1 WHERE id = 2;
UPDATE deadlock_demo SET amount = amount - 1 WHERE id = 1;
두 MariaDB 세션이 서로 반대 행을 기다리다가 deadlock 오류가 발생한 화면
서로 반대 순서로 잠금을 획득하면 순환 대기가 만들어질 수 있다.

증거 수집

SHOW ENGINE INNODB STATUS;

LATEST DETECTED DEADLOCK에서 두 트랜잭션, 대기 인덱스와 관련 SQL을 확인한다. 출력에는 실제 데이터가 포함될 수 있어 공개 전 마스킹한다.

해결 원칙

  1. 모든 코드 경로에서 PK 등 일관된 순서로 잠근다.
  2. 외부 API 호출을 트랜잭션 밖으로 이동해 보유 시간을 줄인다.
  3. 한 번에 갱신하는 행과 인덱스 범위를 줄인다.
  4. 재시도는 1213처럼 재시도 가능한 오류에만 횟수와 지연을 제한한다.
두 트랜잭션이 같은 행 순서로 갱신한 뒤 모두 완료된 결과
잠금 순서를 통일하면 한 트랜잭션이 기다리더라도 순환 대기를 피할 수 있다.

오류 1213을 운영에서 해석하는 방법

재시도를 늘려도 반복된다

증상

요청은 가끔 성공하지만 오류와 지연이 계속된다.

원인

잠금 순서와 트랜잭션 범위가 그대로다.

확인 방법

오류 시각, SQL fingerprint, 트랜잭션 ID와 재시도 횟수를 함께 기록한다.

해결

순환을 만드는 경로를 고친 뒤 제한된 재시도를 보조 수단으로 둔다.

예방

다중 행 갱신은 정렬된 식별자 순서를 테스트로 고정한다.

Lock wait timeout과 혼동한다

증상

오류 코드가 다른데 같은 장애로 집계한다.

원인

순환 감지와 장시간 대기를 구분하지 않았다.

확인 방법

DB 오류 코드와 SQLSTATE를 원문 그대로 기록한다.

해결

Deadlock은 잠금 그래프를, timeout은 긴 트랜잭션과 차단 세션을 조사한다.

예방

두 오류를 별도 지표로 관리한다.

운영 점검 체크리스트

  • 오류 1213과 lock wait timeout을 별도 지표로 기록하는가?
  • 충돌 경로의 잠금 순서가 동일한가?
  • 외부 호출이 트랜잭션 밖에 있는가?
  • 재시도 횟수와 backoff에 상한이 있는가?

참고 자료

한 줄 요약

Deadlock은 재시도로만 숨기지 말고 두 트랜잭션의 잠금 순환을 확인한 뒤 자원 획득 순서와 트랜잭션 범위를 고쳐야 한다.

댓글 0

  • 첫 번째 댓글을 남겨보세요.