728x90
Deadlock원인
- tx1 이 pk=2 레코드에 exclusive lock (x-lock)획득
- tx-2,3 이 중복된 레코드에 대해서 s-lock 이 필요해서 대기
- tx1 commit하면 tx2,3 shared lock 동시획득
- tx2,3 pk=2레코드에 대해서 동시에 x-lock 획득 대기
의문 사항
- 왜 shared lock을 먼저걸고 , exclusive lock을 걸어야 하는가?
- insert시에 pk는 unique해야함으로 해당 record에대해서 s lock을 걸고 확인을 먼저하게 된다.
- 어떻게 이미 삭제된 레코드에 대해서 lock을 걸수 있는가?
- 해당 레코드들을 영구적으로 삭제하지 않고 일정시간 동안 삭제표시만 상태로 유지한다.
(Deletion-mark [Tomb stone]) - 쿼리에서만 해당 레코드가 보이지 않는다.
- 해당 레코드들을 영구적으로 삭제하지 않고 일정시간 동안 삭제표시만 상태로 유지한다.
tx 2,3이 이미 s lock을 잡고있으므로 그 누구도 x lock을 획득못하는 데드락 상황이 발생한것이다.
MySQL Deadlock 감지
- DeadLock detection thread가 모든 트랜잭션이 획득 또는 대기하고 있는 잠금 graph를 계속 감시한다.
- 동시 트랜잭션이 많은 경우, deadlock 체크 작업으로 인한 대기가 발생한다.
- 어떤 회사(구글)에서는 deadlock detection therad를 비활성화 하기도 한다.
- innodb_deadlock_detect = OFF
- innodb_lock_wait_timeout 기본 값은 50초이다. 무한정 대기하지 않음
- innodb_lock_wait_timeout = 2~3초 정도로 조정 검토가 필요하다.
- MySQL은 롤백이 쉬운 트랜잭션을 Victim trx 로 선정한다.
- 롤백이 쉬운 트랜잭션 == undo 레코드가 적은 트랜잭션
- Victim으로 선정된 트랜잭션은 강제 롤백처리
- 남은 트랜잭션은 정상 처리
- 배치 작업과 서비스 쿼리가 경합하면, 항상 배치 프로세스가 살아남게 된다.
MySQL deadlock 해석과 원인 분석은 매우 어려운편이다.
- 동일 SQL문장이더라도 , 항상 동일한 잠금을 사용하지 않는다.
- 현재 데이터 상태에 따라서
- 동시 실행중인 잠금 경합 DML의 실행시점에 따라서
- Record 뿐만 아니라 , Record 간의 간격(gap) 도 잠금(next key lock)의 대상이다.
- deadlock 시점의 관련 트랜잭션을 모두 로깅하지 않는다.
- 사용하는 잠금이나 상황에 따라서 중간 중간 잠금이 해제 되기도 한다.
- 각 잠금의 lifecycle이 다르다. (기본은 트랜잭션 단위)
- 찰나의 시간차이로 deadlock이 발생가능
- 잠금의 대상은 모든 index key (Cluster key , Secondary key, Foreign key)
dead lock에 관한 개발자들의 많은 오해
- 프로그램 코드의 오류로 dead lock이 발생한다.
- 개발능력이나 db 문제로 deadlock이 발생한다.
- dead lock이 발생하면 , 프로그램 코드 개선이 필요하다.
하지만
- dead lcok은 회피 할 수 있는 경우도 있지만, 회피할 수 없는 경우가 더 많다.
- deadlock이 발생했다고 해서 , unique key나 pk를 삭제할 수는 없다.
- (가능하다면 , 모딜링 시점에서 최소화하는게 좋다)
- unique key 같은 경우 , 성능적인 장점보다는 deadlock의 빈도를 높이는 경우가 많다.
- deadlock의 발생빈도와 서비스 영향도에 따라서 무시하는게 좋다 ( 로깅 및 별도의 재처리)
- 프로그램 코드에서의 트랜잭션 재처리
- if (sqlEx.getSqlState() == "40001" { retry;}
- retry 코드를 넣었다고 해서 , 코드 품질이 낮아지는것은 아니다.
728x90
'Database > Real MySQL Season1 ,2' 카테고리의 다른 글
23) 테이블 파티셔닝 (0) | 2024.11.08 |
---|---|
21) Join Update & Join Delete (0) | 2024.11.07 |
19) JSON 타입 활용 (0) | 2024.10.30 |
17) NoWait & Skip Locked , 18) Union vs Union All (0) | 2024.10.24 |
16) Count(*) vs Count(column) (0) | 2024.10.22 |