경쟁상태
INSERT INTO users (name, email, age, city)
SELECT '새 사용자', 'test메일', 25, 'seoul'
WHERE NOT EXISTS (
SELECT 1
FROM users
WHERE email = 'test메일'
);이 쿼리를 처음에 설명해 주실 때
두 개의 프로세스가 동시에 데이터를 확인하고 삽입하려 할 때 경쟁상태가 발생할 수 있다라고 하셨다가
뒤에 이 방식은 사실상 경쟁상태에 무관하다고 정정해주셨는데
그럼 두 개의 프로세스가 동시에 데이터를 확인하고 삽입하려 했을때 무관하다는 의미인가요??
왜 무관한지 잘 모르겠습니다.
답변 1
1
안녕하세요 Cola님 질문 남겨주셔서 감사합니다. 음 우선적으로 제가 촬영하면서 표현이 조금 과한 부분이 있는거 같네요. 조금 정정해서 설명을 드릴게요.
결론부터 말씀드리자면 이거는 트랜잭션 격리 수준에 따라서 다른요소입니다. Defaut인 REPEATABLE READ에서는같은 email이두번들어가는것까지는막아줍니다. 하지만경쟁상태와완전히무관한건아니고, 격리수준에따라결과가달라지며데드락이발생할수있습니다.
그럼 왜 REPEATABLE READ에서는중복이생기지 않을까?
여러분들이 사용하시는 일반 SELECT는 Lock없이 스냅샷 데이터를 읽지만, INSERT ... SELECT 안의 SELECT(여기 예시로는 NOT EXISTS 서브쿼리)는 조금 차이가 있습니다.
REPEATABLE READ에서 InnoDB는이 SELECT가읽는범위에공유(S) next-key 락을겁니다. 그래서 email = 'test메일'을찾는순간그값이들어갈자리에 즉 자리라는걸 갭이라고 표현하는데, 이 갭에락이걸리고, 그걸 갭 락이라고 불러요. 이러면 다른트랜잭션은그자리에 INSERT할수없게됩니다.
또 이렇게 락을 거는 읽기는 스냅샷이 아닌 최신 커밋 데이터를 읽기 떄문에, 먼저 실행된 트랜잭션이 커밋한 row를 후속으로 들어오는 트랜잭션이 볼 수 있죠.
그럼 진짜 트랜잭션이 동시에 실행되면 어떻게 될까?
이거는 제가 예시를 좀 들어보도록 할게요.
T1 : NOT EXISTS 확인 → 없음 → 해당갭에 S 락획득
T2: NOT EXISTS 확인 → 없음 → 같은갭에 S 락획득 (S 락끼리는호환)
T1: INSERT시도 → T2의 S 락때문에대기
T2: INSERT시도 → T1의 S 락때문에대기
서로기다리는데드락 → InnoDB가감지해서한쪽을롤백 (한쪽은 애플리케이션 에러 발생)
즉 결론은 한 건만 들어가고 중복은 생기지 않을꺼에요. 하지만 애플리케이션 상에서의 에러가 발생을 하게 되겠죠.
READ COMMITTED에서는 어떨까요??
해당 격리수준으로 가게 된다면, 이 SELECT는 락 없이 consistent read로 동작을 할 겁니다.
그냥 일반 읽기로 해석하시면 됩니다.
그러면 앞선 예시에서 T1, T2 둘 다 "없음"을 확인하고 둘 다 INSERT해서 같은 건이 드렁 갈 수 있어요.
그래서 어떻게 막는가?
격리 수준에 영향을 받지 않고 중복을 막고 싶다면 UNIQUE 조건을 걸어버리시는게 가장 좋습니다.
그 다음에 INSERT IGNORE나 INSERT ... ON DUPLICATED KEY UPDATE를 쓰거나, 중복 키 에러 등등을 애플리케이션 레벨에서도 고려하시면 좋을꺼에요.
결론 : NOT EXISTS 방식은 UNIQUE 제약을 걸 수 없는 상황에서 쓰는 차선책이다.
0
추가로
https://dev.mysql.com/doc/refman/8.0/en/innodb-locks-set.html
해당 자료도 읽어보시면 도움이 되실꺼에요 ㅎㅎ
좋은 하루 보내세요!! 감사합니다!
stmt
0
5
1
실행 통계2 explain analyze 조인 쿼리
0
12
0
3강 인덱스 구조 강의 자료 문의
1
16
1
Kafka 4.0 zk 코드 제거 가이드 요청
0
9
1
조회 메서드에서 @Transactional(readOnly=true) 질문
1
20
1
19강 감정분석 강의처럼 api 돌렸는데
1
40
1
[해결됨]마지막 강의 내용 수정 화면이 기능을 못하네요.
0
27
1
[해결됨]부분적으로 화면 이동이 안되는 부분이 있습니다.
0
44
6
68강 문제 풀이
0
31
1
현대 쿼리 복잡성에 관한 질문
0
49
3
key_length 가 사용되는곳
0
39
1
낙관적락 질문있습니다.
0
43
1
해당 결제 부분을 포폴에서 테스트 api를 적용에 대한 궁금증
1
40
1
댓글순서부여방식
0
43
1
16강에서 코드가 계속 안도길래. ai가 고쳐서 일단 supabase에 preditc 한 주가를
1
43
1
공통 코드 VS Enum 클래스
1
39
1
movablePageCount와 pageSize 상수
0
36
1
16강 구글 colab 에서 코드 실행이 안돼요.
0
61
1
JPA와 네이티브 쿼리
0
41
1
인덱스 강의 혹은 해당 강의 전 듣어야 하는 사전강의 문의
0
80
2
라이브 운영중인 환경의 테이블에 인덱스 추가시 고려사항
0
109
2
오라클
0
110
1
21강에서 이해하기 어려운 부분들이 있습니다!
0
129
1
인덱스 분할, 병합에 따른 인덱스 적용 기준과 OPTIMIZE TABLE
0
154
2





