🔍 검색 키워드: MySQL Deadlock found when trying to get lock, ERROR 1213 40001 해결, InnoDB 데드락 원인, SHOW ENGINE INNODB STATUS 데드락 확인, innodb_print_all_deadlocks, MySQL 트랜잭션 재시도
요약: MySQL InnoDB의 "ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction"은 여러 트랜잭션이 서로가 가진 락을 기다려 진행하지 못할 때 InnoDB가 한 트랜잭션을 롤백하며 내는 에러입니다. 공식 문서는 데드락이 위험한 것이 아니므로 트랜잭션을 다시 실행할 준비를 하고, 트랜잭션을 짧게 유지하며 락 순서를 통일하고 인덱스를 만들어 발생 가능성을 줄이라고 안내합니다.
MySQL 데드락(ERROR 1213)은 무엇인가요?
MySQL 공식 문서는 데드락을 "여러 트랜잭션이 각자 다른 트랜잭션이 필요로 하는 락을 쥐고 있어서 진행하지 못하는 상황"이라고 정의합니다. 관련된 트랜잭션이 모두 같은 자원이 풀리기를 기다리므로 어느 쪽도 자신이 가진 락을 놓지 않습니다.
MySQL 에러 레퍼런스에 실린 1213번 에러 정보는 다음과 같습니다.
| 항목 | 값 |
|---|---|
| 에러 번호 | 1213 |
| 심볼 | ER_LOCK_DEADLOCK |
| SQLSTATE | 40001 |
| 메시지 | Deadlock found when trying to get lock; try restarting transaction |
같은 문서는 InnoDB가 트랜잭션이 데드락에 걸려 자동으로 롤백될 때 이 에러를 보고한다고 설명합니다. 복구하려면 그 트랜잭션의 모든 작업을 다시 실행해야 합니다.
InnoDB는 데드락을 어떻게 처리하나요?
공식 문서에 따르면 데드락 감지가 켜져 있을 때(기본값) InnoDB는 데드락을 자동으로 감지하고 하나 또는 여러 트랜잭션을 롤백해 데드락을 해소합니다. 이때 InnoDB는 작은 트랜잭션을 골라 롤백하려고 하며, 트랜잭션의 크기는 삽입, 수정, 삭제된 행 수로 판단합니다.
또한 대기 목록(wait-for list)이 200개 트랜잭션을 넘으면 데드락으로 간주하고, 대기 목록을 확인하려던 트랜잭션을 롤백한다고 문서에 적혀 있습니다.
데드락 감지를 끌 수 있나요?
데드락 감지는 innodb_deadlock_detect 변수로 끌 수 있습니다. 문서는 동시성이 높은 시스템에서 여러 스레드가 같은 락을 기다리면 데드락 감지가 속도 저하를 일으킬 수 있고, 때로는 감지를 끄고 innodb_lock_wait_timeout 설정에 의존해 롤백하는 편이 더 효율적일 수 있다고 설명합니다. 다만 감지를 끈 상태에서 어떤 트랜잭션이 롤백되는지는 해당 문서에서 확인되지 않았습니다. 설정을 바꾸기 전에 공식 문서를 확인하세요.
데드락은 어떻게 확인하나요?
공식 문서는 가장 최근 데드락의 원인을 확인하려면 언제든 SHOW ENGINE INNODB STATUS를 실행하라고 안내합니다. 이를 통해 애플리케이션을 데드락이 덜 생기게 조정할 수 있다고 설명합니다.
SHOW ENGINE INNODB STATUS;데드락 경고가 자주 발생해 걱정된다면 innodb_print_all_deadlocks 변수를 켜서 더 폭넓은 디버깅 정보를 모을 수 있습니다. 가장 최근 하나가 아니라 모든 데드락의 정보가 MySQL 에러 로그에 기록됩니다. 문서는 디버깅이 끝나면 이 옵션을 꺼 두라고 안내합니다.
SET GLOBAL innodb_print_all_deadlocks = ON;위 SET 문은 변수를 켜는 일반적인 형태이며 이 글에서 직접 실행해 확인한 것은 아닙니다. 운영 환경에서 설정을 바꾸기 전에 사용 중인 MySQL 버전의 문서와 권한을 확인하세요. 이 글은 SHOW ENGINE INNODB STATUS 출력의 상세 형식은 다루지 않습니다.
데드락은 어떻게 줄이나요?
공식 문서는 데드락 가능성을 줄이는 방법으로 다음을 안내합니다.
- LOCK TABLES 대신 트랜잭션 사용
- 트랜잭션을 작게 유지: 데이터를 삽입하거나 수정하는 트랜잭션이 오랫동안 열려 있지 않도록 합니다.
- 작업 순서 통일: 서로 다른 트랜잭션이 여러 테이블이나 넓은 범위의 행을 수정할 때는 각 트랜잭션에서 같은 순서로 작업합니다(예: SELECT ... FOR UPDATE).
- 인덱스 생성: SELECT ... FOR UPDATE와 UPDATE ... WHERE에서 쓰는 컬럼에 인덱스를 만듭니다.
같은 문서는 격리 수준이 데드락 가능성에 영향을 주지 않는다고 설명합니다. 격리 수준은 읽기 동작을 바꾸지만, 데드락은 쓰기 작업 때문에 생기기 때문입니다. 따라서 격리 수준을 바꾸는 것을 데드락의 해결책으로 기대하기는 어렵습니다.
작업 순서가 어긋나는 예
아래는 락 순서가 서로 반대일 때 일반적으로 데드락이 생기는 구조를 보여 주는 개념 예시입니다. 이 글에서 실행해 확인한 출력이 아니며, 공식 문서가 설명한 "순서가 일관되지 않은 락 요청"을 단순화한 것입니다.
-- 트랜잭션 A
START TRANSACTION;
UPDATE accounts SET balance = balance - 10 WHERE id = 1;
UPDATE accounts SET balance = balance + 10 WHERE id = 2;
-- 트랜잭션 B (동시에, 반대 순서)
START TRANSACTION;
UPDATE accounts SET balance = balance - 10 WHERE id = 2;
UPDATE accounts SET balance = balance + 10 WHERE id = 1;두 트랜잭션이 id 1과 2를 서로 반대 순서로 수정하면 각자 하나씩 락을 쥔 채 상대의 락을 기다릴 수 있습니다. 모든 트랜잭션이 항상 id가 작은 행부터 수정하도록 순서를 통일하는 것이 한 가지 방법입니다.
애플리케이션에서는 어떻게 대응하나요?
공식 문서의 핵심 조언은 "데드락으로 트랜잭션이 실패했을 때 다시 실행할 준비를 항상 하라. 데드락은 위험하지 않다. 그냥 다시 시도하라"입니다. 또 애플리케이션 로직이 올바르더라도 트랜잭션을 재시도해야 하는 경우를 반드시 처리해야 한다고 설명합니다.
1213 에러를 받으면 롤백된 트랜잭션 전체를 처음부터 다시 실행하는 재시도 로직을 두세요. 재시도 횟수와 대기 시간은 애플리케이션 특성에 맞게 정하되, 무한 재시도는 피하는 것이 일반적입니다.
주의할 점
- 롤백된 트랜잭션은 일부만 다시 실행하지 말고 전체 작업을 다시 실행해야 합니다.
- 데드락이 잦다면 재시도로 가리지 말고 트랜잭션 구조와 락 순서, 인덱스를 점검하세요.
- innodb_print_all_deadlocks는 디버깅이 끝나면 꺼 두세요. 에러 로그가 계속 커질 수 있습니다.
- 이 글은 MySQL 8.4 공식 문서를 근거로 정리한 것이며 직접 실행해 확인한 결과가 아닙니다. 버전에 따라 동작과 변수가 다를 수 있습니다.
정리표
| 확인할 것 | 방법 | 근거 |
|---|---|---|
| 에러 의미 | ERROR 1213 (40001) ER_LOCK_DEADLOCK | 에러 레퍼런스 |
| 가장 최근 데드락 원인 | SHOW ENGINE INNODB STATUS | InnoDB 데드락 문서 |
| 모든 데드락 기록 | innodb_print_all_deadlocks 켜기 | 에러 로그에 기록, 디버깅 후 끄기 |
| 발생 줄이기 | 작은 트랜잭션, 같은 작업 순서, 인덱스 | 격리 수준은 영향 없음 |
| 애플리케이션 대응 | 트랜잭션 전체 재시도 | 데드락은 위험하지 않음 |
자주 묻는 질문(FAQ)
MySQL 데드락은 서버 장애인가요?
아닙니다. 공식 문서는 데드락이 위험하지 않으며 트랜잭션을 다시 시도하면 된다고 설명합니다. InnoDB가 한 트랜잭션을 롤백해 데드락을 해소합니다.
ERROR 1213이 나면 어떤 트랜잭션이 롤백되나요?
데드락 감지가 켜져 있을 때 InnoDB는 작은 트랜잭션, 즉 삽입·수정·삭제된 행 수가 적은 트랜잭션을 골라 롤백하려고 합니다.
격리 수준을 낮추면 데드락이 사라지나요?
공식 문서는 격리 수준이 데드락 가능성에 영향을 주지 않는다고 설명합니다. 데드락은 쓰기 작업 때문에 생기기 때문입니다.
가장 최근 데드락 정보는 어디서 보나요?
SHOW ENGINE INNODB STATUS를 실행하면 됩니다. 모든 데드락을 에러 로그에 남기려면 innodb_print_all_deadlocks를 켜고, 디버깅이 끝나면 끄세요.
참고 문서: MySQL - InnoDB Deadlocks · MySQL - Deadlock Detection · MySQL - Deadlocks handling · MySQL - Server Error Reference
최종 업데이트: 2026-11-10 · 작성: 내멋스레 사는 이야기