기본 콘텐츠로 건너뛰기

라벨이 MySQL인 게시물 표시

공유 락과 배타 락의 차이: 읽기와 쓰기를 어떻게 막고 기다리게 할까

공유 락과 배타 락의 차이: 읽기와 쓰기를 어떻게 막고 기다리게 할까 빠른 답 공유 락은 읽은 행을 보호하는 락에 가깝고, 같은 행에 대한 다른 공유 락은 허용하지만 배타 락은 기다리게 합니다. 배타 락은 변경할 행을 독점하는 락에 가깝고, 같은 행에 대한 공유 락과 배타 락 요청을 모두 기다리게 합니다. 일반 SELECT 와 SELECT ... FOR SHARE , SELECT ... FOR UPDATE 는 다릅니다. InnoDB의 일반 조회는 보통 MVCC 스냅샷을 읽고 행 락을 잡지 않습니다. 데드락은 두 트랜잭션이 서로 필요한 락을 이미 상대가 쥐고 있을 때 발생하며, DB가 한쪽을 롤백할 수 있습니다. 목차 한눈에 비교 시간 흐름으로 이해하기 왜 공유 락과 배타 락이 헷갈리는가 예제 쿼리와 결과 해석 실행 계획과 인덱스가 락 범위를 바꾼다 대기 시간을 짧게 보고 실패 처리하기 데드락은 어떤 순서에서 발생하는가 락 대기와 데드락 출력 예시 해석하기 버전 기준과 오래된 설명 차이 한눈에 비교 목적 공유 락은 읽은 데이터가 트랜잭션 도중 바뀌지 않게 보호하는 쪽에 가깝고, 배타 락은 변경 대상 행을 독점하는 쪽에 가깝습니다. 호환성 공유 락끼리는 함께 잡을 수 있지만, 공유 락과 배타 락은 서로 충돌합니다. 배타 락끼리도 충돌합니다. 대표 문법 MySQL InnoDB에서는 SELECT ... FOR SHARE 가 공유 락 기반의 락킹 읽기이고, SELECT ... FOR UPDATE 가 배타 락 기반의 락킹 읽기에 가깝습니다. 일반 조회와의 차이 일반 SELECT 는 보통 consistent read로 처리되어 행 락을 잡지 않습니다. 락을 동반한 읽기가 필요할 때 FOR SHARE 나 FOR UPDATE 를 명시합니다. 인덱스 영향 락은 WHERE 조건 자체보다 실행 계획상 스캔한 인덱스 레코드와 범위에 더 가깝게 걸립니다. 장애 양상 단순 경합은 락 대기로 나타나고, 순환 대기는 데드락으로 감지되어 한쪽 트랜잭션이 실패할 수 있습니다. ...

트랜잭션 격리 수준, 동시성과 정합성 사이에서 어떻게 선택할까

트랜잭션 격리 수준, 동시성과 정합성 사이에서 어떻게 선택할까 빠른 답 트랜잭션 격리 수준은 동시에 실행되는 트랜잭션이 서로의 변경을 어디까지 볼 수 있는지 정하는 설정이다. READ COMMITTED 는 Dirty Read를 막지만, 같은 트랜잭션 안에서 같은 행을 다시 읽었을 때 값이 달라질 수 있다. REPEATABLE READ 와 SERIALIZABLE 은 더 강한 일관성을 제공하지만, DBMS의 MVCC, 락, 인덱스 상태에 따라 성능 영향이 달라진다. 격리 수준은 이름만으로 고르기보다 쿼리 패턴, 트랜잭션 길이, 인덱스, 락 대기 상황을 함께 보고 결정해야 한다. 목차 한눈에 비교 왜 격리 수준은 이름만 외우면 헷갈릴까 선택 기준 매트릭스 세 가지 읽기 이상 현상 예제 테이블과 인덱스 트랜잭션 재현 SQL 실행 계획과 결과 해석 락 대기와 운영 출력 예시 애플리케이션 코드에서의 보완 흔한 오해 한눈에 비교 읽기 기준 READ UNCOMMITTED 는 커밋 전 변경까지 읽을 수 있고, READ COMMITTED 부터는 커밋된 데이터만 읽는다. 반복 조회 READ COMMITTED 에서는 같은 행을 다시 읽을 때 값이 바뀔 수 있고, REPEATABLE READ 는 같은 트랜잭션 안의 반복 읽기를 더 강하게 보장한다. 범위 조회 Phantom Read는 같은 조건으로 다시 조회했을 때 행의 개수나 집합이 달라지는 현상이며, DBMS의 MVCC와 범위 락 구현에 따라 관찰 결과가 달라진다. 동시성 비용 격리 수준이 높아질수록 일관성은 강해질 수 있지만 락 대기, 충돌, 재시도 비용이 늘 수 있다. 선택 기준 단순 조회인지, 결제·재고·계좌처럼 경쟁 상태를 막아야 하는 쓰기인지에 따라 격리 수준과 잠금 전략을 함께 봐야 한다. 왜 격리 수준은 이름만 외우면 헷갈릴까 트랜잭션 격리 수준은 동시에 여러 트랜잭션이 실행될 때 한 트랜잭션이 다른 트랜잭션의 변경을 어떻게 관찰할지 정한다. 낮은 격리 수준은 동시 처리에는 유리할 수 있지만 아직 ...

데이터베이스 인덱스는 왜 조회를 빠르게 만들고, 언제 오히려 느려질까?

데이터베이스 인덱스는 왜 조회를 빠르게 만들고, 언제 오히려 느려질까? 빠른 답 인덱스는 컬럼 값을 정렬해 둔 탐색 구조라서 테이블 전체를 읽지 않고 검색 범위를 줄일 수 있다. MySQL InnoDB의 세컨더리 인덱스 리프 노드에는 실제 레코드 주소가 아니라 PK 값이 저장된다. 조건에 맞는 데이터가 너무 많으면 인덱스 탐색과 PK 재조회가 반복되어 풀 테이블 스캔보다 느릴 수 있다. 인덱스 설계는 쿼리 모양과 EXPLAIN 의 type , key , rows , Extra 를 함께 보며 검증해야 한다. 목차 시간 흐름으로 이해하기 흐름으로 보기 인덱스가 필요한 이유 B+Tree 인덱스의 조회 흐름 InnoDB 세컨더리 인덱스와 PK 재조회 실행 계획으로 확인하기 인덱스 스캔 방식과 해석 포인트 인덱스가 오히려 느려지는 경우 인덱스 설계에서 자주 생기는 오해 시간 흐름으로 이해하기 조건 분석 WHERE , JOIN , ORDER BY , GROUP BY 에 등장하는 컬럼을 확인한다. → 인덱스 탐색 사용할 수 있는 인덱스가 있으면 루트 노드에서 리프 노드까지 내려간다. → 범위 스캔 리프 노드에서 조건에 맞는 키 범위를 순서대로 읽는다. → 레코드 접근 필요한 컬럼이 인덱스에 없으면 PK로 실제 레코드를 다시 읽는다. → 실행 계획 확인 EXPLAIN 으로 실제 선택된 인덱스와 예상 읽기량을 비교한다. 하나의 조회 쿼리는 보통 조건을 해석하는 단계에서 시작한다. 옵티마이저는 사용할 수 있는 인덱스 후보를 보고, 인덱스를 쓰는 편이 나은지 테이블을 직접 읽는 편이 나은지 비용을 추정한다. 인덱스를 선택했다면 B+Tree의 루트 노드에서 시작해 리프 노드까지 내려가고, 리프 노드에서 필요한 범위를 읽는다. InnoDB의 세컨더리 인덱스를 사용한 조회라면 여기서 끝나지 않을 수 있다. 리프 노드에 저장된 PK 값을 이용해 클러스터형 인덱스를 다시 조회해야 할 수 있기 때문이다. 이 재조회가 많아지면 인덱스를 사용했는데도 기대보다 느린 쿼리가 된...