해결된 질문
작성
·
133
·
수정됨
1
안녕하세요.
Skip Locked For Session
강의를 보다가 궁금증이 생겨서 질문을 하게 됐습니다.
Skip Locked For Session
12:14초
의 내용을 보면 왼쪽 터미널에서 SELECT * FROM testLock WHERE name = "ax" order by seq limit 3 for update skip locked
쿼리를 통해서 1개의 row를 받아오는 장면이 나오는데요.
오른쪽 MySQL Workbench에서 트랜잭션을 실행하고 SELECT * FROM testLock WHERE name = "ax" order by seq limit 3 for update
를 통해 Lock을 잡고 있는 상황인데 어떻게 왼쪽 터미널(다른 세션)에서 name
이 ax
인 row를 가져올 수 있는지 궁금합니다.
skip locked
설정이 들어갔으니 lock이 걸린 데이터 (name
이 ax
인 row)는 못 가져와야 하는거 아닌가요 ?? skip locked
를 제외했을 때는 lock 걸린 데이터를 가져와야 하니 timeout이 나는 상황은 이해를 했습니다.
답변 1
1
안녕하세요 denia park님!! 질문 주셔서 감사합니다.
해당 질문에 대해서 저는 이렇게 이해를 하였어요.
MySQL WorkBench에서 Lock을 잡고 있는데, 어떻게 터미널에서 가져 올 수가 있냐??
아무래도 강의가 촬영이 되면서, 여러가지 영상이 중첩이 되다보니 중복된 데이터가 들어간 걸로 보이네요 ㅠㅠ 해당 부분을 검토하지 못해서 죄송합니다.
질문자분이 말씀해 주신 것처럼 다음과 같은 순서로 진행이 된다면, skip locked
옵션이 정상적으로 동작한 케이스 입니다.
MySQLWorkbench - A
터미널 - B
1. A에서 begin 실행
2. A에서 INSERT 실행
3. B에서 SELECT * FROM testLock for update skip locked; 조회
--> 조회해도 데이터를 볼 수가 없음
4. A에서 SELECT 실행
--> 해당 세션에서 이미 INSERT를 한 이력이 있기 떄문에 조회 가능
이 부분은 정확하게 이해를 하신게 맞으십니다. 혼동을 드려서 죄송합니다...
맞습니다.
일반적으로 begin을 진행을 하면 해당 테이블을 복제를 하고 해당 복제본에 데이터를 변경후 커밋을 하게 됩니다.
하지만 커밋이 되기전에 B에서는 복제본의 유무를 알 수가 없기때문에 볼 수 없습니다.
해당 예시는 세션이 충돌났을 때 발생가능한 TimeOut을 보여드리고자 촬영이 되었는데 조금 혼동이 오실수도 있는 부분이 맞겠네요 ㅠㅠ 검토 후 수정하도록 하겠습니다.
For Update는 큰 연관성이 없습니다.
해당 부분은 세션 복제본간의 충돌에 대한 쿼리가 아니라 원자성을 보장하기 위한 옵션이라고 보시면 됩니다.
예를 들어서
X, y 두 유저가 Tx를 전송합니다.
같은 Raw에 대해서 X는 Find
Y는 Update를 실행합니다.
이때 해당 tx가 중복된 시간에 들어오게 된다면
잘못된 케이스에 대해 X가 Y가 update한 데이터를 포함해서 못가져올수가 있습니다.
이러한 상황에 대해 원자성을 보장하기 위해 For Update를 사용하게 됩니다.
예시를 간단하게 들어봤는데 케이스가 이럴때에 유효한 쿼리라고 보시면 됩니다.
보통 동시제어에 대해서 사용을 하는데 티켓팅 서비스 정도에 사용한다 라고 보시면 될꺼 같아요
Client에서 처리하기 보다는 하나의 서버에서 mutex를 관리하기가 용이하기 때문에 사용이 됩니다.
제가 지금 업무중이라서 ㅠㅠ 퇴근 후 도움이 되실만한 정보나 링크 추가해두도록할게요!!
일단 공식 문서는 다음과 같습니다.
- https://dev.mysql.com/doc/refman/8.4/en/innodb-locking-reads.html
그런데 저는 일반적으로 공식문서를 추천해드리지는 않아요.
왜냐하면 공식문서에서는 정발 개발스러운 단어를 사용하면서 설명을 하기 떄문에
단어에 익숙하지 않으면 읽기가 어려운 경우가 있습니다.
물론 공식문서가 가장 중요하고 신뢰가 갑니다.
그래서 저는 이 문서를 먼저 읽어보시기 보다는
어느정도 검색을 해보니 해당 링크가 가장 쉽고 간단하게 알려주시는거 같아서 해당 링크를 추천 드릴게요.
https://tyrionlife.tistory.com/41
실제 예시를 보여드리다 보니 좀 더 해당 글이 좋을 꺼 같습니다.
https://www.cockroachlabs.com/blog/select-for-update/
이 글도 영문이기는 한데, 좀 유익해 보이네요
해당 링크들을 먼저 참고하시고, 이후에 공식문서를 읽어보시면 좀 더 읽기 편하고 추가적인 습득도 가능할꺼 같습니다.
감사합니다!
안녕하세요
빠른 답변 주셔서 정말 감사합니다.
제가 여쭤보고 싶었던 내용은 해당 내용이 맞습니다.
MySQL WorkBench에서 Lock을 잡고 있는데, 어떻게 터미널에서 가져 올 수가 있냐??
중복된 데이터가 있다고 하면 충분히 이해가 되네요.
감사합니다.
그리고 답변 주신 내용에 대해서 한 가지 더 의문점이 있어서 추가적으로 질문을 남깁니다.
A에서 트랜잭션을 열고 데이터를 Insert 했을때 B에서 볼 수 없는 이유는 lock이 걸려서라기 보다는 데이터가 아직 commit이 되지 않아서 보이지 않는게 아닌가요 ??
해당 상황과 for update가 어떤 연관성이 있는지 조금 더 설명을 해주실 수 있으실까요 ??