MySQL Deadlock 오류인 **"Deadlock found when trying to get lock; try restarting transaction"**는 두 개 이상의 트랜잭션이 서로 자원을 점유하고 동시에 다른 트랜잭션에서 필요한 자원을 요청할 때 발생합니다. 이런 상황에서 MySQL은 교착 상태(Deadlock)를 감지하고, 트랜잭션 중 하나를 강제로 중단하여 다른 트랜잭션이 완료될 수 있도록 합니다.
- 두 트랜잭션이 동일한 테이블에서 다른 순서로 레코드에 접근하여 교착 상태를 초래합니다
- 예: 트랜잭션 A가 Row 1 → Row 2를 잠그고, 트랜잭션 B가 Row 2 → Row 1을 잠글 때 발생.
- 한 트랜잭션이 너무 많은 자원을 점유하거나 잠금을 오래 유지하는 경우, 다른 트랜잭션이 대기하다가 데드락이 발생합니다.
- 테이블에 적절한 인덱스가 없으면, MySQL이 더 많은 레코드를 잠그게 되어 불필요한 충돌이 발생합니다.
- 외래 키 제약 조건을 통해 부모/자식 테이블 간의 동시 작업이 충돌할 때 발생.
- 동일한 조건으로 여러 트랜잭션이 UPDATE 또는 DELETE 작업을 시도할 때 데드락이 발생할 수 있습니다.
MySQL에서 교착 상태의 원인을 파악합니다:
SHOW ENGINE INNODB STATUS\G
- 이 명령은 최근에 발생한 데드락 정보를 보여줍니다.
- 관련된 테이블, 트랜잭션 ID, 잠금 대기 상태를 확인할 수 있습니다.
[ 오류 로그 확인 ]
MySQL 서버의 에러 로그에서 데드락 관련 추가 정보를 확인합니다
tail -f /var/log/mysql/error.log
- 모든 트랜잭션이 동일한 순서로 테이블과 레코드에 접근하도록 설계합니다.
- 예: 항상 Row 1 → Row 2 순서로 잠금 요청.
-- 트랜잭션 A
START TRANSACTION;
SELECT * FROM table WHERE id=1 FOR UPDATE;
SELECT * FROM table WHERE id=2 FOR UPDATE;
COMMIT;
-- 트랜잭션 B
START TRANSACTION;
SELECT * FROM table WHERE id=1 FOR UPDATE;
SELECT * FROM table WHERE id=2 FOR UPDATE;
COMMIT;
- 트랜잭션 내부에서 실행되는 쿼리 수를 줄이고, 트랜잭션 범위를 최소화합니다.
- 불필요한 대기 시간을 줄이고 잠금을 효율적으로 사용.
START TRANSACTION;
-- 필요한 작업만 수행
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
COMMIT;
WHERE 조건에 사용되는 컬럼에 적절한 인덱스를 추가하여 불필요한 테이블 스캔과 광범위한 잠금을 방지합니다.
ALTER TABLE orders ADD INDEX (customer_id);
이를 통해 MySQL은 필요한 레코드만 잠그고, 다른 레코드에 영향을 미치지 않게 됩니다.
- 외래 키 제약 조건이 있는 테이블에서 DELETE/UPDATE 작업 시 부모-자식 간의 순서를 명확히 관리합니다.
- 먼저 자식 테이블을 처리한 후 부모 테이블을 처리합니다.
- 잠금 수준을 변경하여 데드락을 방지할 수 있습니다.
- 필요 시 명시적으로 테이블 전체를 잠급니다
InnoDB 잠금 대기 시간 증가
SET innodb_lock_wait_timeout = 50;
데드락을 줄이기 위한 MySQL 설정
innodb_deadlock_detect 설정 활성화
SET GLOBAL innodb_deadlock_detect = ON;
원인 | 해결 방안 |
트랜잭션 잠금 순서 불일치 | 모든 트랜잭션이 동일한 순서로 잠금을 요청하도록 쿼리 구조 변경. |
트랜잭션 범위가 너무 큼 | 트랜잭션 범위를 최소화하고 작업을 빠르게 종료. |
적절한 인덱스가 없음 | WHERE 조건에 사용되는 컬럼에 적절한 인덱스 추가. |
외래 키 제약 조건 충돌 | 부모-자식 순서에 맞게 쿼리를 실행하고, 외래 키 제약을 재검토. |
트랜잭션 충돌로 인한 데드락 | 애플리케이션에서 재시도 로직 추가 및 MySQL 설정 최적화 |
데드락은 시스템 성능에 심각한 영향을 미칠 수 있으므로, 쿼리와 트랜잭션 구조를 설계할 때 이를 사전에 방지하는 것이 중요합니다. 문제가 발생했을 때는 SHOW ENGINE INNODB STATUS 명령어를 활용해 원인을 파악하고, 위의 해결 방안을 단계적으로 적용해 보세요.
[MYSQL] 접속에러 (10061/2003) 원인 및 해결방법 (1) | 2024.12.04 |
---|---|
Mybatis org.xml.sax.SAXParseException: 요소 콘텐츠는 올바른 형식의 문자 데이터 또는 마크업으로 구성되어야 합니다 (0) | 2022.05.13 |
[MYSQL] sql 오류 (1136) column count doesn't match value count at row 1 원인 (0) | 2022.05.09 |