• mysql
  • innodb
  • book

Real MySQL 8.0 Ch.6~7 — 데이터 압축과 암호화

InnoDB의 페이지 압축과 테이블 압축의 동작 방식과 한계, I/O 레이어에서 처리되는 데이터 암호화와 성능 영향을 정리한다.

시리즈 · Computer Science 서적4 / 8
  1. Real MySQL 8.0 Ch.4 — MySQL 엔진과 스레드 구조
  2. Real MySQL 8.0 Ch.4 — InnoDB 스토리지 엔진 아키텍처
  3. Real MySQL 8.0 Ch.5 — 트랜잭션과 잠금
  4. Real MySQL 8.0 Ch.6~7 — 데이터 압축과 암호화
  5. Real MySQL 8.0 Ch.8 — B-Tree 인덱스
  6. Real MySQL 8.0 Ch.8 — R-Tree, 전문 검색, 함수 기반, 멀티 밸류 인덱스
  7. Real MySQL 8.0 Ch.8 — 클러스터링 인덱스, 유니크 인덱스, 외래키
  8. Real MySQL 8.0 Ch.9 — 옵티마이저와 기본 데이터 처리

데이터 압축이 필요한 이유

디스크에 저장된 데이터 파일의 크기는 쿼리 처리 성능뿐 아니라 백업 및 복구 시간과도 밀접하게 연결된다.

파일이 클수록 쿼리를 처리하기 위해 더 많은 데이터 페이지를 버퍼 풀로 읽어야 한다. 새로운 페이지가 계속 적재되면 그만큼 더티 페이지도 더 자주 디스크로 기록돼야 한다.

페이지 압축

Transparent Page Compression이라고도 한다.

  • 디스크에 저장하는 시점에 데이터 페이지를 압축하고, 디스크에서 읽어 올 때 압축을 해제한다.
  • 버퍼 풀에 한 번 적재된 페이지는 압축이 해제된 상태로만 관리된다.
  • 그래서 MySQL 서버의 내부 코드에서는 압축 여부와 관계없이 투명(Transparent)하게 동작한다.

펀치 홀

문제는 16KB 데이터 페이지를 압축한 결과가 얼마가 될지 예측할 수 없다는 점이다. 그런데 적어도 하나의 테이블은 동일한 크기의 페이지로 통일돼야 한다. 이를 해결하기 위해 펀치 홀(Punch hole) 기능을 사용한다.

OS의 블록 크기가 512바이트일 때 동작 과정은 다음과 같다.

  1. 16KB 페이지를 압축한다(결과를 7KB로 가정).
  2. 디스크에 압축 결과 7KB를 기록하고, 나머지 9KB는 빈 데이터로 기록한다.
  3. 7KB 이후의 9KB 공간에 펀치 홀을 생성한다.
  4. 파일 시스템은 7KB만 남기고 나머지 9KB를 OS에 반납한다.

펀치 홀은 OS뿐 아니라 하드웨어에서도 지원해야 한다. 이런 제약 때문에 실제로 페이지 압축은 많이 사용되지 않는다.

테이블 압축

OS나 하드웨어에 대한 제약 없이 사용할 수 있어 더 일반적으로 쓰인다. 디스크의 데이터 파일 크기를 줄일 수 있다는 이득이 있지만 단점도 분명하다.

  • 버퍼 풀 공간 활용률이 낮다.
  • 쿼리 처리 성능이 낮다.
  • 데이터 변경이 빈번하면 압축률이 떨어진다.

압축 테이블 생성

  • 테이블이 별도의 테이블스페이스를 사용해야 한다(innodb_file_per_table).
  • ROW_FORMAT=COMPRESSED와 함께 KEY_BLOCK_SIZE로 압축된 페이지의 목표 크기를 지정한다.
  • InnoDB 페이지 크기가 16KB라면 목표 크기는 4KB 또는 8KB로 지정한다. 페이지 크기가 32KB, 64KB인 경우에는 테이블 압축을 사용할 수 없다.
CREATE TABLE compressed_table (
  c1 INT PRIMARY KEY
) ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8;

압축 과정

목표 크기가 8KB일 때 다음과 같이 진행된다.

  1. 16KB 데이터 페이지를 압축한다.
    • 압축 결과가 8KB 이하이면 디스크에 저장한다.
    • 8KB를 초과하면 원본 페이지를 스플릿해 2개의 페이지에 8KB씩 저장한다.
  2. 나뉜 페이지 각각에 대해 1번 단계를 반복한다.

이 과정에서 InnoDB I/O 레이어는 아무 역할도 하지 않는다. I/O 레이어에서 투명하게 처리되는 페이지 압축과 다른 점이다.

목표 크기를 잘못 설정하면 목표 크기가 될 때까지 페이지를 계속 스플릿하므로 성능이 급격히 떨어질 수 있다.

데이터 암호화

MySQL 8.0부터는 데이터 파일뿐 아니라 리두 로그, 언두 로그, 복제를 위한 바이너리 로그까지 모두 암호화할 수 있다.

MySQL 서버의 암호화는 데이터베이스 서버와 디스크 사이에서 데이터를 읽고 쓰는 지점, 즉 I/O 레이어에서만 실행된다. 디스크 입출력 이외의 부분에서는 암호화 처리가 전혀 필요하지 않다.

암호화와 성능

  • 디스크에서 읽은 데이터 페이지는 복호화되어 버퍼 풀에 적재된다. 한 번 메모리에 적재되면 암호화되지 않은 테이블과 동일한 성능을 보인다.
  • 버퍼 풀에 없는 데이터를 읽을 때는 복호화가 필요해 쿼리 처리가 그만큼 지연된다.
  • 반대로 암호화해서 디스크에 저장하는 작업은 쿼리를 처리하는 스레드가 아니라 백그라운드 스레드가 수행한다. 따라서 저장 때문에 사용자의 쿼리가 지연되지는 않는다.
  • AES 암호화는 평문이 짧으면 암호화 키의 크기에 따라 결과가 더 커질 수 있다. 하지만 데이터 페이지는 암호화 키보다 훨씬 크므로 암호문의 크기가 평문과 같다.

결국 암호화한다고 해서 버퍼 풀의 효율이 달라지거나 메모리 사용 효율이 떨어지지는 않는다.

참고

  • Real MySQL 8.0