인사이트

인사이트리포트

디지털프렌스포메이션 최신 정보 및 트렌드를 제공합니다.

SW 테크놀로지 오픈소스 SW

MariaDB 서버 모니터링 및 성능 최적화: InnoDB Buffer Pool 2부

2023.11.23임주연 프로
다운로드

들어가며

DB Query의 성능이 느려질 수 있는 이유는 여러가지가 있는데, 그 중 Memory 사용은 성능에 상당한 영향을 준다. Memory가 부족하면 새로운 데이터를 읽기 위해 오래된 데이터 블록이 Buffer Cache에서 자주 제거되고, 다시 Disk로부터 읽어와서 Buffer Cache에 할당하여 읽어야 하기 때문이다.

이처럼 Buffer Cache의 효과적인 활용이 보장되지 않으면 데이터 액세스가 불필요하게 발생될 수 있으며 이로 인해 성능이 느려질 수 있기 때문에, 데이터 적재 및 관리를 위한 Buffer Pool에 대한 이해가 필요하다.

이번 2부 인사이트 리포트에서는 MariaDB의 Buffer Pool을 모니터링 하고 최적화 하기 위하여 확인해야 할 시스템 변수 및 상태 변수를 알아보고 Buffer Pool의 상태에 따라 어떤 고려 사항이 있는지 알아 보고자 한다.

 

BufferPool의 주요 변수 및 모니터링

앞서 설명한 Buffer Pool의 내용을 기반으로 확인해야 할 변수가 무엇인지, 변수 설정 시 고려할 사항이 무엇인지 살펴보겠다.

1. Buffer Pool 관련 모니터링 지표

MariaDB와 같은 오픈소스데이터베이스는 데이터베이스의 상태를 모니터링하고 분석하는 자료가 상용 솔루션 대비 많지 않기 때문에, 상태정보를 수집하여 분석하는 것이 성능을 모니터링하고 관리하는데 무엇보다 중요하다. 특히 상태 변수(GLOBAL STATUS) 모니터링은 주기적으로 상태 지표 값을 수집하여 트랜드를 분석하는 것이 중요하다.

일반적으로 Buffer Pool 뿐만 아니라 데이터베이스의 전반적인 모니터링과 성능 분석에 필요한 지표 값을 찾기 위해서는 아래의 내용을 확인하고 있다.

 

2. InnoDB Buffer Pool Size

1) Innodb_buffer_pool_instances

Buffer Pool의 주요 구성요소로는 하나의 인스턴스 내에 인스턴스 관리 리스트 및 Data Page가 저장되는 Chunk 등으로 구성되어 있다.

10.5 이전까지는 Buffer Pool을 크게 가져가는 경우에 많은 트랜잭션이 발생할 때 뮤텍스 경합 등으로 인한 성능 저하를 우려하여 인스턴스 분할을 통한 메모리 경합을 최소화 하고자 하였다. 그러나, 인스턴스 분할 구성이 항상 성능 개선에 도움이 되는 것은 아니었으며 도움이 되는 경우에도 성능개선이 크지 않음을 확인하였다. 결국 10.5 버전 이후 InnoDB Buffer Pool은 단일 인스턴스 구조로 변경되었다. 이런 구조적 변경에 의해 “innodb_buffer_pool_instances” 시스템 변수는 Deprecated(10.5 버전) 되었고, 결국 삭제(10.6부터) 되었다.

2) Innodb_buffer_pool_size와 Innodb_buffer_pool_chunk_size

“Innodb_buffer_pool_size”는 최근에는 서버 물리 메모리의 70 ~ 80% 정도 내에 할당을 권고하고 있으며, 10.8 이하를 사용하고 있으면서 할당 할 메모리가 대용량일 경우 몇 가지 고려해야 할 사항이 있다.

 

MariaDB 의 “Setting Innodb Buffer Pool Size Dynamically” 문서에 따르면 내부적으로“innodb_buffer_pool_size”를 할당하는 계산 공식은 다음과 같다.

[참고 – https://mariadb.com/kb/en/setting-innodb-buffer-pool-size-dynamically/]

 

이 때 성능 문제를 방지하기 위해서는  “innodb_buffer_pool_size/inodb_buffer_pool_ chunk_size”로 계산된 청크의 수는 1000을 초과하지 않도록 권고하고 있다.

예를 들어, Buffer Pool Size를 300G 로 할당 할 경우 “innodb_buffer_pool_ chunk_size”를 128MB로 구성하게 되면 생성되는 chunk의 수는 2400개가 될 것이기 때문에 이런 경우는 Chunk Size를 300MB 이상으로 조정 해 줄 필요가 있다.

이와 같이 10.7 버전까지는 대용량의 메모리를 구성 할 때 Buffer Pool Size 대비 Chunk Size를 적절하게 조정하여 과도하게 Chunk 수가 증가되는 것을 방지하는 것이 필요하다.

10.8.1 이상부터는 “innodb_buffer_pool_chunk_size”의 기본값이 “autosize (0)” 로 변경 되었으며, Buffer Pool 크기에 따라 자동으로 크기가 조정(“innodb_buffer _pool_size”/64) 된다.

그리고 “innodb_buffer_pool_chunk_size”설정 값이 “innodb_buffer_pool_size” 설정 값 보다 우선 적용 되므로, Chunk Size에 따라 Buffer Pool Size가 일부 조정 될 수 있음을 참고하기 바란다.

 

3) Buffer Pool Size의 적정성

InnoDB Buffer Pool의 가장 중요한 서버 시스템 변수는 “innodb_buffer_pool_size” 이다. 이 변수의 크기는 SQL 요청이 필요로 하는 데이터들이 충분히 로드 될 수 있도록 커야 한다. 이 변수의 크기 조정을 위한 지표들의 모니터링을 위한 상태 변수는 다음과 같다.

Buffer Pool에 Cache되어 있는 데이터를 읽은 비율을 모니터링 하기 위해서는 모든 Read Request와 Disk에서 직접 읽은 Read 수에 대한 비율을 확인해야 한다. 공식 문서에는 ““innodb_buffer_pool_reads”의 변경 사항이 “innodb_buffer_pool_read_requests” 변경사항의 1% 미만이면 사용량이 많다” 라고 이야기 하고 있다. 따라서 Buffer Cache Ratio가 낮고 “innodb_buffer_pool_wait_free”가 증가하는 경우 Buffer Pool이 부족 하거나 Flush가 자주 발생하는지 확인해야 하다.

Buffer Pool의 크기 조정 작업이 동적으로 진행되는 상황을 확인하려면 “innodb_buffer_pool_resize_status” 값을 통해 어느 시점에 조정되었는지 알 수 있다.

 

 

3. Buffer Pool 워밍업 관련

서버를 다시 시작한 후 데이터 로딩 시간(워밍업)을 줄이기 위해 InnoDB 서버 종료 시 Buffer Pool에 대한 내용을 기록하여 DB 서버 기동 후에 이 Page를 복원하는 작업을 할 수 있다.

“innodb_buffer_pool_dump_pct”에 설정된 Dump 비율을 참고하여 Buffer Pool의 Page 정보를 파일로 저장하게 되고, “innodb_buffer_pool_filename” 변수를 통해 Buffer Pool Dump가 포함된 파일명을 지정할 수 있다. 이 파일에는 Tablespace ID 및 Page ID 정보를 가지고 있어서 Startup 할 때 해당 정보를 가지고 데이터를 로딩 하게 된다.

사용량이 많은 서버를 다시 시작한 후에는 일반적으로 Buffer Pool에 있던 Disk Page의 내용을 대부분 메모리로 다시 가져오기 때문에 이러한 준비기간을 단축하게 된다. 또한 I/O 요청을 대규모 배치로 수행할 수 있으므로 전체 I/O 속도가 빨라지게 되며, 이러한 Page 로딩은 Background에서 작업되기 때문에 데이터베이스 시작을 지연시키지 않는다.

 

 

4. Disk 동기화 관련

1) InnoDB Read I/O Threads 및 InnoDB Write I/O Threads

InnoDB Read I/O와 InnoDB Write I/O 의 역할은 다음과 같다.

InnoDB는 다양한 유형의 I/O요청을 처리한다. 10.4이전 버전까지 “innodb_read_io_threads” 및 “innodb_write_io_threads” 시스템 변수로 사용하여 Data Page에서 읽기 및 쓰기 I/O를 서비스하는 백그라운드 스레드 수를 구성할 수 있고, 만일 서버가 I/O 요청을 기다리는데 많은 시간이 소요되는 것으로 나타나면 I/O Thread 수를 조정해야 할 수도 있다.

10.4 버전까지 InnoDB는 “innodb_read_io_threads”, “innodb_write_io_threads” 시스템 변수로 설정된 수의 Read/Write Threads가 생성되어 작업을 수행 했지만, 10.5부터는 InnoDB I/O Thread는 InnoDB Background Thread Pool를 사용하도록 변경되었으며 Asynchronous I/O 기능으로 Background에서 내부 작업을 수행한다.

그리고 10.5 이후부터는 이 변수의 용도가 변경되었는데, 각 시스템 변수의 값에 “256”을 곱하여 Background Thread Pool에서 완료할 수 있는 최대 Concurrent Asynchronous I/O 요청 수를 제한하게 된다.

예를 들어, innodb_read_io_threads=2 및 innodb_write_io_threads=4로 설정한 경우, InnoDB는 최대 512개 (2 x 256)의 Concurrent Asynchronous Read I/O 요청과 1024개 (4 x 256) Concurrent Asynchronous Write I/O 요청으로 제한하게 된다.

InnoDB Background Thread Pool은 아래 표와 같이 여러 범주에서 내부 작업을 수행하고 있다.

 

Asynchronous I/O가 활성화 되면, Query Thread는 I/O 요청을 운영체제에 직접 요청하여 처리(Native AIO)하므로 InnoDB Background Thread는 단순히 I/O 요청 완료를 기다리게 된다. 요청이 완료되고 Background Thread는 I/O가 완료되었다는 응답을 받으면 I/O 이벤트 대기가 풀리게 된다.

 

2) 초당 I/O 작업 수

“innodb_io_capacity” 변수는 Buffer Pool에서 Page를 Flush하고 Change Buffer에서 데이터를 병합하는 등 InnoDB Background 작업에 사용할 수 있는 초당 I/O 작업 수(IOPS)를 말한다. 이 변수는 동적 변경이 가능하며 이 값을 조정 검토해야 할 상황은 다음과 같다.

  • Change Buffer 지연 감소
  • Idle Flushing 속도 높이기 (LSN이 일정한 경우)
  • Dirty Page 비율 Flush 속도 높이기

이 값은 사용 중인 Drive 유형에 따라 시스템이 처리할 수 있는 초당 I/O 작업 수 정도로 설정해야 하며, 동적으로 설정이 가능하기 때문에 서버의 부하가 높은 시점을 처리하기 위한 값으로 높게 설정해 놓고 일반적인 상황에서는 줄여서 사용 할 수도 있다.

InnoDB에 사용할 수 있는 최대 I/O 용량은 “innodb_io_capacity_max” 변수를 설정하여 “innodb_io_capacity”의 상한 값을 설정할 수 있다.

그러나 “innodb_io_capacity”를 너무 높게 설정하게 되면 Buffer Pool에서 너무 빨리 제거되기 때문에 캐싱 효율성이 떨어질 수 있으므로, 시스템 상황에 대해 충분히 모니터링하여 설정하는 것이 필요하다.

 

 5. Page Flush 관련

InnoDB Page Cleaner Thread는 Flush 목록 및 LRU Flush를 수행하여 Buffer Pool에서 Dirty Page를 Flush하는 역할을 수행한다. Purge 작업은 삭제된 행을 제거하고, history list에서 UNDO 목록을 제거한다.

“innodb_page_cleaners”는 Page Cleaner threads 수를 정의하는 변수로 기본값은 4이다. 10.5 이전까지는 “innodb_buffer_pool_instances”를 사용하였기 때문에 “innodb_buffer_pool_instances” 설정 값과 “innodb_page_cleaners” 의 설정 값을 비교하여 둘 중 더 작은 값으로 “innodb_page_cleaners”에 설정되었다. 10.5.1 이후부터는 Buffer Pool의 인스턴스를 분할하는 구조가 사라졌기 때문에 단일 Page Cleaner만 사용된다.

 

1) Dirty Page 공간 비율

InnoDB의 Buffer Pool에서 Disk에 기록되지 않은 Dirty Page 비율을 지정할 수 있으며, 내용은 다음과 같다.

Dirty Page는 “innodb_max_dirty_pages_pct”에 설정된 비율을 초과하면 Flush가 발생하며, 이후부터는 더 적극적인 Dirty Page Flush를 위해 “innodb_max_dirty_ pages_pct_lwm”에 설정된 비율 초과 시 Flush가 발생한다. 만일 Dirty Page Limit값에 도달하게 되면 Buffer Pool의 공간이 부족하지 않더라도 Dirty Page Flush가 발생될 수 있다.

“innodb_max_dirty_pages_pct” 시스템 변수의 최적 값은 워크로드 및 데이터 액세스 패턴에 따라 다르다. DML이 많은 워크로드환경에서 이 변수 값을 너무 낮게 설정하면 Dirty Page Flush가 너무 자주 발생하여 I/O 성능에 악영향을 미친다. 마찬가지로, 이 변수의 값을 너무 높게 설정하면 너무 많은 양의 Dirty Page Flush가 발생하여 과도한 Write에 의한 병목현상이 발생할 수 있으므로 주의가 필요하다.

 

2) Buffer Pool Usage 관련 상태 변수

Buffer Pool Flushing 등의 작업이 적절하게 발생되고 있는지 모니터링 할 필요가 있으며, 이와 관련된 상태 변수는 다음과 같다.

참고로 대부분의 Buffer Pool지표는 메모리 Page 수로 보여주기 때문에 그 상태 값을 바로 확인하기가 유용하지 않다. 그래서 Page 수 기준으로 상태 값을 확인 할 때는 Page 수에 “innodb_page_size”에 설정된 변수 값을 곱해서 Bytes로 변환하여 확인하는 것이 유용하다.

“innodb_buffer_pool_pages_data” 값을 통해 Buffer Pool의 데이터 사용량을 확인 할 수 있다.

 

3) LRU Scan

LRU Scan 단위를 지정하는 변수는 아래와 같다.

매 초마다 Background Flush Thread는 Disk에 쓸 수 있는 Dirty Page를 찾기 위해 모든“innodb_buffer_pool_instances”에서 “innodb_lru_scan_depth”에 정의된 깊이만큼의 LRU 목록을 검색한다. 이 때 Flush 된 Page는 해제되고 “innodb_buffer_pool_pages_free”에 추가된다. 만일 “innodb_lru_scan_lengh”를 증가시키면 서버에 더 많은 Free Page가 필요로 하기 전에 Dirty Page가 Disk에 기록 될 가능성이 높아질 수 있다. 반대로, 너무 공격적인 Flushing은 그 자체로 I/O를 높일 수 있으며 Caching의 효율성을 떨어뜨릴 수 있으므로 너무 늘리는 것은 권장하지 않는다.

 

4) Buffer Pool Page 사용량

Buffer Pool Page 전체 사용량 대비 Page Free 상태를 모니터링을 하면 Buffer Pool의 Flush를 통해 Free 확보가 얼마나 자주 발생되는지, Buffer Pool 영역이 사용량 대비 과하게 할당되어 Free가 지속적으로 많이 존재하지 않는지 등에 대해 모니터링 할 수 있다.

5) Buffer Pool Dirty Page 비율

Buffer Pool에서 Flush한 페이지 수를 확인하기 위해서는 “innodb_buffer_pool_pages_flushed” 값을 통해 확인 할 수 있으며, Flush 발생에 대한 모니터링을 하기 위해서는 “innodb_buffer_pool_pages_total” 대비 “innodb_buffer_pool_pages_dirty”의 발생량을 확인하여 Dirty Page의 비율을 통해 확인할 수 있다. Dirty Page의 비율이 높을 경우 Flush가 빠르게 발생되고 있는지 등을 확인이 가능하다.

 

6) Buffer Pool Free Page 대기

“innodb_buffer_pool_wait_free”는 Buffer Pool의 Free Page를 얻기 위해 대기한 횟수를 나타내며, 이 수치가 증가하는 경우는 Page Flush 중이거나 Flush 되는 속도보다 Page를 찾는 요청이 더 많을 경우 증가하게 된다.

 

마치며

InnoDB 스토리지 엔진의 성능 최적화 중 Buffer Pool과 관련된 내용에 대해 살펴보았다. MariaDB의 Buffer Pool은 데이터 처리 속도와 성능 향상을 위한 핵심 요소이며, 적절한 크기 설정과 Hit Ratio 개선을 통해 데이터베이스 시스템의 성능을 향상시켜 메모리 관리를 통해 Buffer Cache의 효율성을 유지하고, 데이터 액세스 과정에서 불필요한 디스크 액세스를 최소화함으로써 데이터베이스의 전체적인 성능을 향상시킬 수 있다.

이 리포트를 통해 Buffer Pool에 대한 이해와 성능에 대한 고민에 조 이나마 도움이 되었기를 바란다.

 

 

# References

- https://mariadb.com/kb/en/innodb-buffer-pool/
- https://dev.mysql.com/doc/refman/8.0/en/innodb-buffer-pool.html
- https://mariadb.com/kb/en/setting-innodb-buffer-pool-size-dynamically/
- https://mariadb.com/kb/en/innodb-page-flushing/
- https://mariadb.com/kb/en/innodb-system-variables/
- https://mariadb.com/kb/en/mariadb-memory-allocation/
- https://mariadb.com/kb/en/understanding-mariadb-architecture/
- https://mariadb.com/kb/en/setting-innodb-buffer-pool-size-dynamically/
- https://mariadb.com/docs/server/architecture/components/enterprise-server/innodb/background-thread-pool/
- https://mariadb.com/docs/server/storage-engines/innodb/operations/configure-io-threads/
- https://www.percona.com/blog/tuning-mysql-innodb-flushing-for-a-write-intensive-workload/
- Exem Deep Internals Series II – Oracle, PostgreSQL, MySQL Core Architecture II (㈜엑셈)

임주연 프로

임주연 프로

소프트웨어사업부 OSS사업팀

에스코어 OSS기술그룹에서 오픈소스DB와 관련된 전문가로 기술지원 업무를 하고 있습니다.

연관 아티클

  • LangChain의 새로운 라이브러리 LangGraph 훑어보기
    SW 테크놀로지2024.10.17

    LangChain의 새로운 라이브러리 LangGraph 훑어보기

    자세히 보기
  • K8S 깐깐하게 운영하기 : 계정 권한 부여
    2024.09.26

    K8S 깐깐하게 운영하기 : 계정 권한 부여

    자세히 보기
  • Elastic VectorDB: 고성능 검색의 미래
    2024.09.05

    Elastic VectorDB: 고성능 검색의 미래

    자세히 보기