작성자 없음
작성자 정보가 삭제된 글입니다.
작성
·
88
·
수정됨
0
해당 강의와 직접적으로 연관있지는 않으나, Lock 관련하여 공부하던 중 성욱님의 MySQL GAP Lock (두번째 이야기) 글을 보게 되었습니다.
우선 정말 많은 도움이 되었음에 감사드리며, 해당 글 관련하여 질문을 드리고 싶습니다. (SELECT FOR UPDATE와도 관련있는 내용이라, 이곳 게시판을 통해 질문 드립니다.)
위 글의
'왜 supremum 레코드를 잠그나요 ?' 단락에서, 8, 9 번째 과정을 보면 다음과 같습니다.
8. 다음 페이지에서 id=137 보다 큰 (첫번째) 레코드인 id=138 읽기
9. WHERE 조건에 일치하지 않으므로 잠금 걸지 않음
그런데 그 아래에서 다음과 같은 내용을 말씀해 주십니다.
'REPEATABLE-READ 격리 수준을 사용하는 MySQL 서버에서는 검색하고 스캔했던 인덱스 레코드를 잠근다는 아주 기본적인 규칙 때문에 잠금이 발생하고 있었던 것이죠. 사용자 데이터가 아닌 시스템 레코드(supremum)까지도 말이죠.'
그러나 이 설명에 따르면, '왜 supremum 레코드를 잠그나요 ?' 에서 언급한 동작에 모순이 발생하는 것 같습니다.
5,6,7 번 과정에서는 supremum record를 읽었기에 잠갔음에도 불구하고,
8, 9번의 과정에서는 id=138 읽었지만 잠그지 않고 종료했기 때문입니다.
위 내용이 모순된 것이라 가정하고,
왜 supremum record에 Lock이 걸리도록 동작했는지에 대한 이유를 개인적으로 찾아보고 공부한 내용들에 기반하여 추측해 보았습니다. (아직 내용을 완벽히 공부하지 못해 틀린 내용이 있을 수 있습니다. 혹시 틀린 부분이 있다면 지적해주시면 감사하겠습니다!)
MySQL 의 공식 문서의 내용에 따르면, Gap Lock은 Gap Lock 의 기준이 되는 index record 이전의 간격을 잠급니다.
A next-key lock on an index record also affects the “gap” before that index record
- MySQL 공식문서 - Next Key Lock
그러나 Gap락이 특정 index record 이전의 간격을 잠근다는 위 설명에 따르면, 어떤 index의 가장 마지막 record 이후의 간격을 잠글 수 있는 방법이 없어집니다. (Gap Lock 은 이전 간격을 잠그는 것이므로)
따라서, 마지막 record 이후의 값을 잠글 수 있기 위해 supremum pseudo record 를 두었을 것이라 예상합니다.
supremum pseudo record(인덱스가 가질 수 있는 가상의 가장 큰 값) 에 대한 GAP Lock은 supremum pseudo record 이전의 간격들을 잠그기 때문입니다.
이는 공식 문서의 다음과 같은 내용을 통해 뒷받침할 수 있을 것 같습니다.
'Suppose that an index contains the values 10, 11, 13, and 20. The possible next-key locks for this index cover the following intervals, where a round bracket denotes exclusion of the interval endpoint and a square bracket denotes inclusion of the endpoint:'
(negative infinity, 10]
(10, 11]
(11, 13]
(13, 20]
(20, positive infinity)
For the last interval, the next-key lock locks the gap above the largest value in the index and the “supremum” pseudo-record having a value higher than any value actually in the index. The supremum is not a real index record, so, in effect, this next-key lock locks only the gap following the largest index value.
- MySQL 공식문서 - Next Key Lock
이를 바탕으로 '왜 supremum 레코드를 잠그나요 ?' 의 원인을 분석해보면 다음과 같습니다.
- 우선 3,4 번 과정에서 id=137 인 index record를 읽습니다.
- 이때 id는 PK 이므로 값이 유니크하기에, BETWEEN 136 AND 137 조건을 통해 137이라는 값을 찾았으면, 해당 값이 조건을 만족하는 가장 마지막 값이라는 것을 알 수 있습니다.
- 따라서 id=138 을 더 이상 탐색하지 않고 종료하게 되는데, 이때 id=137은 해당 PK 인덱스(리프노드 페이지) 의 가장 마지막 값이므로, supremum 레코드를 이용하여 추가적인 간격을 잠구는 것이지 않을까 하는 생각이 들었습니다.
위 부분에 대한 성욱님의 의견을 듣고 싶어 질문드렸습니다.
---
이와 별개로, 추가 궁금증이 있습니다.
1. MySQL 공식 문서에서도 언급되었던 InnoDB performs row-level locking in such a way that when it searches or scans a table index, it sets shared or exclusive locks on the index records it encounters. 라는 문장에서 검색되거나 스캔된 의 의미가 잘 이해되지 않습니다.
예를 들어, id를 PK로 갖는 어떤 테이블에서, id = 3 인 row 를 탐색하기 위해서는,
B-tree의 root 부터 시작 ~ leaf 노드로 이동 후, leaf node의 페이지의 전체 데이터를 스캔해야 하지 않나요?
예를 들어 id=3 인 record 가 들어있는 leaf 노드의 페이지에 id가 1 ~ 5 까지 있다고 하면,
leaf 노드의 페이지로 진입하여 1부터 순차 탐색을 진행할 것 같은데, 그렇게 되면 1~5 까지의 index 값 사이에서 3을 탐색하는 데 1과 2를 먼저 찾을 것이므로, id가 1, 2, 3인 row가 모두 잠겨야 하지 않나 하는 생각이 들었습니다.
혹시 공식문서에서 언급한 검색 혹은 스캔된의 의미가, 조건에 사용된 인덱스가 걸린 필드 값만 확인하는 것은 포함하지 않는 것일까요?
(ex - 위 예시에서
id가 1인 인덱스 확인
조건에 부합되지 않으므로 넘어감. (스캔되었다고 보지 않음)
id가 2인 인덱스 확인
조건이 부합되지 않으므로 넘어감
id가 3인 인덱스 확인
조건에 부합되므로 나머지 값 읽어옴.)
위 내용들에서, 제가 어떤 부분을 잘못 생각하고 있는지 알 수 있을까요?
정말 좋은 강의와 글 공유해 주셔서 감사합니다.
답변 1
0
안녕하세요, 인프런 AI 인턴입니다. 신동훈님께서 궁금해하시는 GAP 락과 관련한 MySQL의 동작 방식에 대해 설명드리겠습니다. 특히, SELECT FOR UPDATE와 관련된 InnoDB의 동작에 대해 문의주셨습니다.
우선, GAP 락(Gap Lock)은 InnoDB의 트랜잭션 격리 수준에서 발생하는 특별한 잠금 메커니즘입니다. 이는 데이터베이스의 일관성과 무결성을 유지하기 위해 사용되며, 주로 데이터 삽입/업데이트 시 비충돌성을 보장하는 것이 목표입니다.
질문해주신 부분에서는 MySQL의 REPEATABLE READ 격리 수준에서의 특성과 관련해 오류가 발생한 것처럼 보였을 수 있습니다.
Supremum Pseudo-Record 락의 실제 작동: MySQL의 InnoDB 엔진은 레코드를 스캔할 때, 각 페이지의 ‘supremum’이라고 불리는 가상의 가장 큰 값에 대한 레코드를 읽고 종종 이를 잠급니다. 이 과정은 페이지의 끝 범위를 보호하기 위한 것으로, 실제 데이터 레코드에는 영향을 주지 않습니다. SELECT ... FOR UPDATE
쿼리 시, InnoDB는 조건에 맞지 않는 레코드라 하더라도 인덱스를 오가는 중이라면 잠금이 설정될 수 있습니다.
BETWEEN 조건에 대한 추가 탐색: PRIMARY KEY가 존재할 경우에도, InnoDB는 보통 쿼리 범위 전체를 커버하기 위해 필요 이상의 잠금을 설정할 수 있습니다. 138보다 작은 값 범위 전체에서 잠금을 걸며 일관성을 유지하게 됩니다.
이를 보다 자세히 이해하기 위해 추가적인 참고 자료를 추천드립니다. 아래 링크에서 Supremum Record 및 Gap과 관련된 정보와 InnoDB의 잠금 설정 방식을 확인하실 수 있습니다:
저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변과 작성하신 자료를 바탕으로 유사한 답변 링크를 추천해드리고 있습니다. 이러한 참고 자료를 통해 이해를 높이실 수 있을 것입니다.
현재 베타 기능으로, 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 더 궁금하신 사항이 있으시면 언제든지 질문해 주세요. 곧 지식공유자 혹은 다른 전문가분들이 더 정확한 답변을 제공해주실 것입니다.