• MySQL 슬로우 쿼리 로그 고찰

    운영 중인 MySQL 서버의 long_query_time이 0초로 잘못 설정되어 있어서 굉장히 많은 수의 슬로우 쿼리가 로깅되고 있는 상황이라고 가정해보자. 거기에다가 QPS는 100만 이상이다. 쿼리가 점점 적체 및 지연되기 시작할 것이고, 디스크 사용량이 증가하게 될 것이다. 그리고 대부분은 그 이유의 주된 원인으로 로깅 작업에 의한 CPU 사용율과 Disk I/O 증가를 꼽을 것이다. 그런데 사실 로깅 작업은 로그를…

  • PostgreSQL 시퀀스 갭(Sequence Gap)

    최근 어느 개발자분이 “PostgreSQL에서 시퀀스를 건너뛰는(jump) 현상은 언제 발생하나요?” 라는 아주 중요한 질문을 했다. 시퀀스를 건너뛰는 현상은 또 다른 말로 시퀀스 갭이라고도 하는데, DB 서버를 운영하다보면 흔히 겪게되는 현상 중 하나이다. 하지만 시퀀스 사이에 갭이 존재한다고 해서 그 모든 갭들이 시퀀스 갭이 되는 것은 아니다. 레코드가 삭제되어도 갭이 발생할 수 있고, 업데이트가 되어도 갭이 발생할…

  • PostgreSQL 통계에 대한 무작위 고찰-1

    선택도(Selectivity) PostgreSQL의 옵티마이저는 쿼리 성능을 최적화하기 위해 FROM, WHERE, JOIN과 같은 다양한 조건절의 선택도(selectivity)를 추정한다. 선택도를 추정한다는 의미는 전체 레코드 수에서 조건을 만족하는 레코드 수의 비율이 얼마나 되는지를 추정한다는 의미이다. 선택도 값에 따라 옵티마이저는 테이블을 스캔할지, 인덱스를 사용할지, 어떤 조인 순서를 택할지 등 가장 효율적인 실행 계획을 결정한다. 수학적으로는 다음과 같이 표현된다. 즉 레코드 1개가…

  • B-Tree 인덱스의 깊이에 대해서

    MySQL 테이블의 B-Tree 인덱스 깊이는 아무리 대용량 테이블이더라도 5단계 이상 깊어지지 않는다. 실제로도 그러할까? 넌 리프 페이지(Non-Leaf Pages)와 리프 페이지(Leaf Pages)의 포맷을 기준으로 이를 간단히 검증해보자. B-Tree 인덱스는 루트(Root)-브랜치(Branch)-리프(Leaf) 노드로 구성되지만 루트 노드는 B-Tree 크기에 따라서 넌 리프 노드일 수도 있고, 리프 노드일 수도 있다. 때문에 검증은 세 단계 분류(Root, Branch, Leaf)가 아닌 두 단계…

  • 전문 검색 인덱스의 트랜잭션 핸들링과 MVCC의 관계

    아래 테스트 결과를 보면 InnoDB의 전문 검색(full-text search)은 격리 수준(=REPEATABLE-READ)이 적용되지 않는 것처럼 보인다. 오히려 커밋된 데이터를 읽는 READ-COMMITTED 격리 수준이 적용된 것처럼 보인다 ▼ CASE 1 세션 1 세션 2 BEGIN; SELECT * FROM t1 WHERE MATCH(title) AGAINST (‘postgresql’ IN NATURAL LANGUAGE MODE);===== 1. row =====id: 3title: Aurora PostgreSQL Databasecontent: NULL UPDATE t1 SET…

  • InnoDB 행 잠금의 2원 2규칙

    InnoDB 행 잠금의 2원 2규칙에 대해 설명하기에 앞서 개요가 조금 필요할 것 같아 살짝 지루한 이야기를 먼저 해보겠다. MySQL 서버의 InnoDB 스토리지 엔진에는 아래와 같이 3가지의 행 잠금 알고리즘이 존재한다. 그리고 당연한 이야기처럼 들리겠지만 이 중 넥스트 키 락은 갭 락과 레코드 락이 결합된 형태의 잠금 알고리즘이다. (역사적으로) 데이터베이스 시스템에서는 팬텀 리드(Phantom Read) 문제를 해결하기…