2025-08-21
오늘 배운 것
플로이드 워셜(Floyd-Warshall)
- 언제 사용하면 좋은지
- 모든 쌍의 최단 거리가 필요할 때 혹은 도달 가능 여부 체크할 때
- 정점 수 N이 작고(대략 4~800 이하), 간선 밀도와 무관하게 단순하거나 확실한 해법이 필요할 때
- 음수 가중치 허용 하지만 음수 사이클은 최단거리 정의 불가함
- 개념
- 정점 k를 중간지점으로 허용/비허용하며 i->j 최단거리르 갱신
dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j])
- 3중 루프
- 복잡도
5.3 InnoDB 스토리지 엔진의 잠금
- InnoDB 스토리지 엔진은 MySQL에서 제공하는 잠금과는 별개로 스토리지 엔진 내부에서 레코드 기반의 잠금 방식을 탑재 → 뛰어난 동시성 처리 제공
5.3.1 InnoDB 스토리지 엔진의 잠금
- 레코드 기반의 잠금 기능 제공
- 잠금 정보가 상당히 작은 공간으로 관리
- 락 에스컬레이션 : 레코드 락 → 페이지락, 테이블락으로 레벨업
- 락 에스컬레이션이 없음
5.3.1.1 레코드 락
- 레코드 자체만을 잠금
- InnoDB스토리지 엔진은 레코드 자체가 아니라 인덱스의 레코드를 잠금
- 인덱스가 하나도 없는 테이블이더라도 내부적으로 자동 생성된 클러스터 인덱스를 이용해 잠금을 설정
- 보조 인덱스를 이용한 변경 작업 → 넥스트 키 락, 갭락 사용
- PK나 유니크 인덱스에 의한 변경 작업 → 레코드 자체에 대해서만 락을 검
- 유니크 인덱스 : 해당 컬럼(들)의 조합이 테이블 내에서 중복되지 않도록 강제하고 검색 성능을 높이는 인덱스 (예 → 이메일, 주민번호)
5.3.1.2 갭락
- 레코드와 바로 인접한 레코드 사이의 간격만을 잠그는 것
- 레코드와 레코드 사이의 간격에 새로운 레코드가 생성되는 것을 제어
- 단독으로 쓰이기 보단 넥스트 키 락의 일부로 주로 사용
5.3.1.3 넥스트 키 락
- 레코드 락과 갭락을 합쳐놓은 형태의 잠금
- 팬텀현상을 막음
- 사용 예시
- 바이너리 로그를 STATEMENT 포맷으로 기록
- STATEMENT 포맷 : SQL문 그자체를 기록
- 레플리카 서버에 해당 로그대로 그대로 실행 시, 넥스트 키락을 걸지 않으면 팬텀현상 발생 가능
- 근데 이렇게 하면 데드락이 자주 발생
- 따라서 ROW 형태로 로그 포맷 바꾸는 것이 좋음
- 행 자체(before/after 이미지)를 기록하는것
- 복제 불일치에 강함
- 하지만 로그 크기는 커질 수 있음
5.3.1.4 자동 증가 락
- AUTO_INCREMENT : 자동 증가하는 숫자 값을 추출하기 위한 속성
- 이 컬럼이 사용된 테이블에 동시에 여러 레코드가 INSERT되는 경우, 저장되는 각 레코드는 중복되지 않고 저장된 순서대로 증가하는 일련번호 값을 가져야 함
- InnoDB 스토리지 엔진은 이를 위해 내부적으로 AUTO_INCREMENT락 이라고 하는 테이블 수준의 잠금을 사용
- 새로운 레코드를 저장하는 쿼리에서만 필요
- 트랜잭션과 관계없이 INSERT나 REPLACE 문장에서 AUTO_INCREMENT 값을 가져오는 순간만 락이 걸렸다가 즉시 해제
- 두 개의 INSERT 쿼리가 동시에 실행되는 경우 하나의 쿼리가 AUTO_INCREMENT락을 걸면 나머지 쿼리는 AUTO_INCREMENT 락을 기다려야 한다
- 명시적으로 획득하고 해제하는 방법은 없음
5.3.2 인덱스와 잠금
- InnoDB는 레코드를 잠그는 것이 아닌 인덱스를 잠그는 방식으로 처리
- 따라서 변경해야 할 레코드를 찾기 위해 검색한 인덱스의 레코드를 모두 락을 걸어야 한다.
- 적절한 인덱스가 준비되어 있지 않다면 각 클라이언트 간의 동시성이 상당히 떨어져서 한 세션에서 UPDATE 작업을 하는 중에는 다른 클라이언트는 그 테이블을 업데이트하지 못하고 기다려야 하는 상황이 발생할 수 있음
- 심지어 인덱스가 하나도 없으면 테이블을 풀스캔하면서 UPDATE 작업을 하게됨
5.3.3 레코드 수준의 잠금 확인 및 해제
- 레코드 수준의 잠금은 테이블 레코드 각각에 잠금이 걸리기 때문에 그 레코드가 자주 사용되지 않는다면 오랜 시간 동안 잠겨진 상태로 남아 있어도 잘 발견되지 않음
- MySQL 5.1 부터는 information_schema, MySQL 8.0부터는 performance_shcema의 data_locks와 data_lock_waits테이블로 잠금 대기를 확인 할 수 있음
- 강제적으로 잠금 해제 하려면 해당 프로세스를 강제종료(KILL)하면 됨
- IX 잠금 : 특정 레코드에 대해서 쓰기 잠금