동시성 제어를 위한 가장 보편적인 방법은 락을 통한 줄세우기
쓰기락과 읽기락
락을 통해 동시성을 제어할 때는, 락의 범위를 최소화 하는 것이 중요
→ 락을 잡는동안 수행하는 작업의 범위를 최소화 하는 것
- 락의 범위가 크면 클수록 락을 획득하기 위한 여러 트랜잭션들이 대기하는 시간이 길어짐 → 그만큼 성능도 내려간다.
- 락의 범위가 길어질수록 Connection Pool을 점유하는 시간이 길어짐 → 최악의 경우에는 Connection Pool 고갈로 이어질 수 있음
MySQL에서는 트랜잭션의 커밋 혹은 롤백시점에 잠금이 풀림 → 트랜잭션이 곧 락의 범위
- 따라서 여기서는 락의 범위를 최소화 한다는 것은 하나의 트랜잭션을 최소화 한다는 것임
- 예시) 만약 S3이미지를 업로드 한다고 했을 때 이것이 트랜잭션 범위안에 들어가게 된다면, S3 네트워크 상태에 따라서 트랜잭션이 굉장히 길어질 수 있음 → 이런 경우에는 외부 네트워크 의존성이나 외부 I/O 가 발생하는 것들은 가능하면 최대한 트랜잭션 범위 밖에서 해주는 것이 좋음
MySQL에서는 쓰기락, 읽기락 두 가지 잠금을 제공
- 읽기락이 잠금을 획득한 상태에서 다른 읽기락이 들어온다면, 읽기락끼리는 잠금 공유가 가능 (대기 없이 데이터 읽기 가능)
- 읽기락 : SELECT … FOR SHARE
- 쓰기락은 잠금 획득(데이터를 점유하고 있는 상태)을 하면 어떤 것이 들어와도 무조건 대기가 발생
- 쓰기락 : SELECT … FOR UPDATE 또는 UPDATE, DELETE 쿼리
하지만, 매번 잠금이 발생할 경우, 성능저하를 피할 수 없음 → MySQL에서 일반 SELECT(FOR SHARE 혹은 FOR UPDATE 또는 UPDATE, DELETE 가 없는 SELECT)는 nonblocking consistent read로 동작(대기 없는 동작)
이것이 가능한 이유는 Undo Log를 통해서 원본 데이터를 변경했을 때, 커밋이 되기 전에 데이터를 계속 관리하고 있기 때문에 가능한 것
레코드 락
MySQL에서 잠금은 row가 아니라 인덱스를 잠근다. → 인덱스가 없는 조건으로 Locking Read시 불필요한 데이터들이 잠길 수 있음
- 락을 잡을 때도 인덱스에 따라서 락의 범위가 달라지기 때문에 인덱스 설정이 매우 중요하다.
추가로 공부해볼만 한 것들
- Java에서의 동시성 이슈 제어방법
- 분산 환경에서의 동시성 이슈 제어방법
- MySQL의 넥스트 키락이 등장한 배경
- MySQL 외래키로 인한 잠금
- MySQL 데드락
2023 KAKAO Tech Campus_BackEnd 필수 과정
DB(MySQL) 강의 정리 내용입니다.
'🔍 CS > 데이터베이스' 카테고리의 다른 글
동시성 제어하기 - 07. 읽기와 쓰기의 트레이드 오프 (0) | 2023.06.07 |
---|---|
동시성 제어하기 - 04. 낙관적 락 (0) | 2023.06.07 |
동시성 제어하기 - 01. 멀티 스레드 환경에 대한 이해 (0) | 2023.06.07 |
데이터 정합성 보장을 위한 트랜잭션 이해하기 - 04. 트랜잭션 격리레벨 (0) | 2023.06.07 |
데이터 정합성 보장을 위한 트랜잭션 이해하기 - 02. 트랜잭션 A, C, I, D (0) | 2023.06.07 |