데이터베이스/MySQL

회사코드 DeadLock 처리 정리

dev_roach 2021. 9. 20. 17:33
728x90

Deadlock Error 처리

에러 발생

위와 같이 DeadLock 이 나는 경우가 종종 잦아지는데 이유는 위와 같이 동일 요청이 두번오게 되는데 이 시점에 데드락걸릴 확률이 상당히 높습니다.

일단 간단히 데드락이 나는 이유를 위해서 코드를 봐야하는데 코드는 대략적으로 아래와 같은 구조입니다.

문제

  1. 해당 푸시 토큰과 같은 로우면를 업데이트 하고, 아니면 INSERT 해라 (INSERT... ON DUPLICATE KEY UPDATE)
  2. 해당 푸시 토큰과 유저 아이디가 같은 로우를 찾는 쿼리
  3. 푸시 토큰을 넘겨받았으면 nil 로 바꿔라 (어플리케이션 로직)
    • 같은 푸시 토큰을 가지고 있는 로우가 있는데 유저가 다르다면 있다면 그건 nil 로 바꿔버려라

즉 위의 코드를 봤을때 중복 요청이 들어오면 충분히 데드락을 발생시킬 수 있습니다. 아래 그림과 같은 상황이 오게될테니 말이죠

이런 상황이 펼쳐질 수 있습니다.

3번 쿼리는 하나의 트랜잭션에서 배치성으로 이루어지는 쿼리이므로 한 트랜잭션이 여러 row 에 대한 쓰기 잠금을 풀었다 잠궜다가 할 수 있게 됩니다. 그래서 중복요청이 들어오게 되면 데드락이 걸릴 확률이 증가하게 됩니다.

해결 방안

중복 요청을 제거하자.

이 쿼리는 중복으로 일어나면 일어날 수록 데드락 확률이 증가한다.

따라서 메소드 안에서 중복 요청을 막아야 할까? 하지만 이 메소드를 쓰는 곳이 항상 중복 체크를 필요로 할까는 의문이다.

따라서 메소드 자체는 단순히 쿼리를 작업하는 일을 하고, 중복 처리 요청은 다른 곳에서 해야할 것 같았다.

지금 발생하는 이유를 로그를 찾아올라가 보니 유저 로그인에서 발생하고 있었다.

같은 시간대 History 가 두개를 생긴게 보니 따닥이 분명하다.

로그인 하는 곳에서 Redis 를 만료시간을 이용해서 duplicate 를 처리했다.

728x90

'데이터베이스 > MySQL' 카테고리의 다른 글

인덱스 스캔 방식  (0) 2021.11.08
MySQL Index  (0) 2021.10.31
MySQL Lock System  (0) 2021.10.25
MySQL 에 쿼리가 들어왔을때?  (0) 2021.10.21
InnoDB 엔진의 특성  (2) 2021.10.12