MySQL Deadlock 발생하는 문제(Sqlalchemy)

내가 Python(Flask 프레임웍)으로 개발했던 서비스에서 월 초만 되면 api 에러가 발생했다. DB는 MySQL, ORM으로는 Sqlalchemy를 사용했다. API 에러는 다음과 같았다.

OperationalError 에러이고, 락을 가져오려고 할 때, Deadlock이 발견됐으니까 트랜잭션을 다시 시작하라는 내용이다.

문제가 되는 부분을 찾았는데, insert 하고, commit 하는 부분이었다.

그래서 에러메시지 내용에 따라 예외 처리를 했다.

이 상태에서 예외를 처리하지 않으면, 다시말해서 rollback을 하지 않으면 이 API(세션)는 더 이상 DB Select 조차 할 수 없다. 그 때 발생하는 에러는 다음과 같다.

Dead Lock 발생으로 서비스가 되지 않는 문제는 rollback으로 해결했다. 이제 Dead Lock이 걸리는 원인을 찾아야겠다.

일단 2개의 Mysql 이벤트가 있다.

  • 이벤트 A : 월마다 한 번 오전 9시에 A 테이블에 파티션 추가하는 프로시저 실행
  • 이벤트 B : 매일 한 번 오전 11시에 B 테이블에 파티션 추가하는 프로시저 실행

특이사항은:

  • 스토리지 엔진은 MyISAM.
    • 엔진 자체가 트랜잭션을 지원하지 않으므로, Sqlalchemy가 애플리케이션 단에서 처리하는 것 같음.
  • 매일 11시에 INSERT가 많이 발생한다.
  • lock 걸렸는지 확인한 결과 문제가 없었다.
  • 에러가 발생하고, Wait 상태인 프로세스도 없었다.
  • API만 재시작하면 정상 동작한다. 이것은 그 세션만 문제라는 얘기다.

그래서 개발서버에서 재현하려고 시도했다. jMeter로 API에 Insert를 대량 발생시켰다. 그러나 에러는 발생하지 않았다.

여러가지 설정도 바꿔봤지만 Dead Lock은 전혀 발생하지 않았다.

  • concurrent_insert
  • table_lock_wait_timeout

개발서버와 실서버의 mysql 버전 차이도 영향이 있을까?

  • Development : 5.1.73-log
  • Production 5.5.27-log

실서버에서는 발생하는게, 왜 개발서버에서는 발생하지 않을까? 정확한 원인은 찾지 못했지만, 이벤트에서 테이블 락을 걸어주고 프로시저 작업이 끝나면 락을 풀어줘야겠다. 에러가 발생하는지 확인해봐야겠다.

댓글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다