This repository was archived by the owner on Mar 15, 2025. It is now read-only.
픽 태그 리스트 수정 시 발생했던 데드락 문제 해결기 #645
sangwonsheep
started this conversation in
메모장
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
개요
픽에 태그 추가, 삭제 시 에러가 발생했다는 이슈입니다.
왜 에러가 발생했는지 알아보기 위해 로그를 확인하였더니 데드락 문제임을 확인할 수 있었습니다.
이를 어떻게 해결했는지에 대한 과정을 설명하도록 하겠습니다.
1차 수정
PickService의 updatePick 메서드에 있는 트랜잭션 제거
트랜잭션의 범위를 줄이면, 데드락 문제가 해결될 것이라 예상하여 트랜잭션 제거
데드락 문제 해결될 것이라 예상하였으나, LazyInitializationException 예외 발생
원인
지연 로딩
으로 연관 관계를 지어놓은 상태반환 타입은 Pick Entity
Pick Entity를 dto로 변환
할 때,Link에 접근
하려고 하여 지연 로딩 예외가 발생한 것해결 방안
1차 시도한 방법
결론
2차 수정
픽의 태그를 삭제할 때 버그 발생 - ObjectOptimisticLockingFailureException
원인
ObjectOptimisticLockingFailureException
예외 발생낙관적 락(
@Version
)을 사용해야만 해당 예외가 발생할 것으로 예상하였다.이 예외는 낙관적 락이 충돌하거나 버전 불일치하는 경우에 발생한다.
낙관적 락을 사용하지 않았는데 예외가 발생한 이유는 무엇일까?
작업이 0개의 행에 영향을 미치면, 예외가 발생한다.
예측되는 예외 발생 시나리오
PickTag
엔티티를 읽는다.PickTag
엔티티를 삭제한다.삭제 작업은 0개의 행에 영향을 미치게 된다.
해결 방안
동시에 여러 트랜잭션이 같은 엔티티를 수정하거나 삭제해서는 안된다.
하나의 트랜잭션이 엔티티에 접근했으면 다른 트랜잭션은 접근해서는 안된다.
이 문제를 해결하기 위해 낙관적 락을 사용할까? 비관적 락을 사용할까?
위와 같은 상황에 비관적 락이 적합하다고 볼 수 있다.
다만 충돌이 많이 일어나지 않는 경우에는 오히려 낙관적 락이 더 좋다고 볼 수 있다.
update가 아닌 delete이기 때문에 충돌이 많이 발생할 것 같지 않다는 생각이다.
그 이유로 낙관적 락을 선택하였다.
또 다른 이유로는 비관적 락은 실제 DB row에 락을 걸기 때문에 낙관적 락에 비해 무겁고 성능에 영향을 미칠 수 있다.
해결 과정
낙관적 락을 선택한 것은 알겠지만, 낙관적 락으로 이 문제를 어떻게 해결해야 할까?
아래와 같은 순서로 진행하였다.
낙관적 락을 설정하고 재시도 로직을 추가하지 않으면
ObjectOptimisticLockingFailureException
예외를 발생시키는 문제가 동일해진다.해당 예외가 발생했을 때 재시도를 통해 다른 트랜잭션이 완료될 때까지 기다렸다가 작업을 재시도한다.
3번의 재시도에도 버전이 맞지 않지 않으면 예외를 던진다.
낙관적 락, 재시도를 적용했을 때 동작 과정
PickTag
를 삭제한다.PickTag
를 삭제하려고 하면 버전이 불일치하게 되어 예외가 발생PickTag 테이블에서 데이터를 가져온 엔티티를 가지고 삭제하도록 변경
why? 낙관적 락 version을 이용하려면 엔티티가 필요함.
결론
참고
https://www.inflearn.com/community/questions/228082/%EA%B8%B0%EB%B3%B8%ED%82%A4-%EC%A0%84%EB%9E%B5-max-1-%EB%AC%B8%EC%9D%98
https://developer-nyong.tistory.com/74
3차 수정
원인
첫 번째 시도였던 트랜잭션 범위를 좁혔지만 데드락 문제를 해결하지 못했음.
데드락 문제를 해결하기 이전에 데드락이 왜 발생했고, 어느 테이블에서 발생하는지 분석이 필요했다.
MySQL 콘솔에 들어가서 데드락을 분석했다.
-- InnoDB 상태 SHOW ENGINE INNODB STATUS;
해당 쿼리로 어느 테이블에서 데드락이 발생했는지 확인할 수 있다.
해당 테이블에 걸린 잠금이 왜 데드락을 유발했는지 시스템을 분석해서 해결해야 한다.
해당 쿼리는 데드락 분석하는데 도움이 되는 쿼리이다.
해당 로그는
SHOW ENGINE INNODB STATUS
결과다.데드락 상황
트랜잭션 1
pick
테이블의 PRIMARY 인덱스에서 특정 레코드(heap no 15
)에 대해 X Lock보유
pick_tag
테이블의 PRIMARY 인덱스에서 특정 레코드(heap no 6
)에 대해 X Lock획득 대기
트랜잭션 2
pick_tag
테이블의 PRIMARY 인덱스에서 특정 레코드(heap no 6
)에 대해 X Lock보유
pick
테이블의 PRIMARY 인덱스에서 특정 레코드(heap no 15
)에 대해 X Lock획득 대기
교착 상태
데드락 발생 이유
해결
비관적 락
참고
https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=cmw1728&logNo=220942833368
Beta Was this translation helpful? Give feedback.
All reactions