---
title: "Buffer Pool warmup: dump/load와 재시작 직후 성능 안정화 전략"
description: "MySQL InnoDB Buffer Pool warmup의 dump/load 동작과 재시작 직후 성능 저하를 줄이는 운영 전략을 정리한다."
tags: [ MySQL, InnoDB, 성능최적화, 운영 ]
image: "mysql-report-bg.png"
published: "2026-06-02"
updated: "2026-06-02"
author: "MySQL 기술 노트"
source_url: ""
---

## 1. 왜 Buffer Pool warmup이 운영에서 중요한가

MySQL 서버를 재시작하면 프로세스 메모리에 있던 InnoDB Buffer Pool은 사라진다. 데이터 파일과 redo log는 디스크에 남아 있지만, 자주 읽히던 인덱스 페이지와 데이터 페이지는 다시 메모리로 올라와야 한다. 이 시기를 흔히 cold cache 구간이라고 부른다. 서비스 입장에서는 같은 SQL이 재시작 전에는 수 밀리초에 끝나다가, 재시작 직후에는 디스크 읽기 때문에 갑자기 느려지는 현상으로 나타난다.

운영자는 재시작 자체보다 재시작 직후의 성능 안정화 시간을 더 조심해야 한다. 계획 점검, minor version 업그레이드, parameter 변경, OS 패치, 장애 복구처럼 재시작이 필요한 작업은 피할 수 없다. 그러나 재시작 후 트래픽을 바로 받으면 다음 문제가 발생할 수 있다.

- 읽기 지연 증가: 자주 쓰는 secondary index와 hot data page가 아직 Buffer Pool에 없다.
- I/O burst: 애플리케이션 요청이 동시에 cold page를 읽으면서 storage read IOPS가 급증한다.
- connection pile-up: 느려진 쿼리 때문에 connection과 thread가 쌓이고, 정상 상태보다 더 큰 부하가 만들어진다.
- 장애 오판: 재시작 후 일시적인 cache miss를 영구 성능 문제나 optimizer 문제로 오해한다.

InnoDB는 이를 완화하기 위해 Buffer Pool dump/load 기능을 제공한다. 서버 종료 시 Buffer Pool에 있던 페이지의 식별 정보를 저장하고, 다음 시작 시 그 페이지들을 다시 읽어 Buffer Pool을 데운다. 이 기능은 모든 문제를 해결하는 마법이 아니라, 재시작 직후의 성능 곡선을 완만하게 만드는 운영 장치다.

## 2. Buffer Pool은 무엇을 기억하고 무엇을 잃는가

InnoDB Buffer Pool은 테이블과 인덱스 페이지를 캐시하는 메모리 영역이다. 쿼리가 B-tree index를 탐색하거나 clustered index에서 row를 읽을 때, 필요한 page가 Buffer Pool에 있으면 memory hit가 발생한다. 없으면 tablespace 파일에서 page를 읽어 Buffer Pool에 적재한다.

중요한 점은 Buffer Pool이 단순한 파일 캐시가 아니라 InnoDB 내부의 page 관리 구조라는 것이다. 각 page는 대략 다음 상태와 관계를 가진다.

- free list: 아직 사용되지 않았거나 재사용 가능한 frame
- LRU list: 최근 접근성과 scan 저항성을 반영해 관리되는 page 목록
- flush list: 변경되었지만 아직 data file에 기록되지 않은 dirty page 목록
- hash/search 구조: page lookup과 adaptive hash index 같은 내부 최적화 구조

서버가 정상 종료되면 dirty page는 checkpoint와 flush 과정을 통해 정리된다. 그러나 메모리에 있던 clean page 자체는 프로세스 종료와 함께 사라진다. dump/load는 page 내용을 통째로 저장하지 않는다. 대신 다음 시작 때 다시 읽을 page의 위치 정보를 저장한다. 즉 “이전에 어떤 tablespace의 어떤 page가 hot set에 가까웠는가”를 기억하고, 실제 page 내용은 시작 후 data file에서 다시 읽는다.

```mermaid
flowchart TD
    A[운영 중 Buffer Pool] --> B[자주 접근된 page 식별]
    B --> C[Buffer Pool dump 파일에 page id 저장]
    C --> D[MySQL 재시작]
    D --> E[Buffer Pool load thread가 page id 읽기]
    E --> F[data file에서 page를 다시 읽음]
    F --> G[재시작 직후 cold cache 구간 완화]
```

이 구조 때문에 dump/load에는 두 가지 운영적 의미가 있다.

첫째, dump 파일은 데이터의 복사본이 아니다. backup도 아니고 crash recovery 수단도 아니다. dump 파일이 없어도 MySQL은 정상적으로 시작할 수 있으며, 데이터 정합성은 redo/undo/checkpoint 체계가 담당한다.

둘째, load는 결국 I/O 작업이다. 시작 직후 Buffer Pool을 데우기 위해 일부 page를 읽어야 하므로 storage에 부하를 준다. 적절히 사용하면 애플리케이션 트래픽이 cold page를 무작위로 읽는 것보다 안정적이지만, 너무 많이 load하면 시작 시간이 길어지거나 storage I/O가 시작 시점에 몰릴 수 있다.

## 3. dump/load 관련 주요 변수와 상태

MySQL 8.0 이상에서 운영자가 우선 확인해야 할 변수는 다음과 같다.

- `innodb_buffer_pool_dump_at_shutdown`: 정상 종료 시 Buffer Pool page id를 dump할지 여부
- `innodb_buffer_pool_load_at_startup`: 시작 시 dump 파일을 기반으로 page를 load할지 여부
- `innodb_buffer_pool_dump_pct`: Buffer Pool에서 dump할 page 비율
- `innodb_buffer_pool_filename`: dump 파일명
- `innodb_buffer_pool_dump_now`: 수동 dump 트리거
- `innodb_buffer_pool_load_now`: 수동 load 트리거
- `innodb_buffer_pool_load_abort`: 진행 중인 load 중단

아래 쿼리는 현재 서버의 관련 설정과 dump/load 상태를 확인한다.

```sql
SELECT VERSION() AS mysql_version;

SHOW VARIABLES
WHERE Variable_name IN (
  'innodb_buffer_pool_dump_at_shutdown',
  'innodb_buffer_pool_load_at_startup',
  'innodb_buffer_pool_dump_pct',
  'innodb_buffer_pool_filename'
);

SHOW STATUS
WHERE Variable_name IN (
  'Innodb_buffer_pool_dump_status',
  'Innodb_buffer_pool_load_status'
);
```

실행 결과(MySQL 8.0.46):

```text
mysql> SELECT VERSION() AS mysql_version;

+---------------+
| mysql_version |
+---------------+
| 8.0.46        |
+---------------+
1 row in set (0.00 sec)

mysql> SHOW VARIABLES
    -> WHERE Variable_name IN (
    ->   'innodb_buffer_pool_dump_at_shutdown',
    ->   'innodb_buffer_pool_load_at_startup',
    ->   'innodb_buffer_pool_dump_pct',
    ->   'innodb_buffer_pool_filename'
    -> );

+-------------------------------------+----------------+
| Variable_name                       | Value          |
+-------------------------------------+----------------+
| innodb_buffer_pool_dump_at_shutdown | ON             |
| innodb_buffer_pool_dump_pct         | 25             |
| innodb_buffer_pool_filename         | ib_buffer_pool |
| innodb_buffer_pool_load_at_startup  | ON             |
+-------------------------------------+----------------+
4 rows in set (0.01 sec)

mysql> SHOW STATUS
    -> WHERE Variable_name IN (
    ->   'Innodb_buffer_pool_dump_status',
    ->   'Innodb_buffer_pool_load_status'
    -> );

+--------------------------------+--------------------------------------------------+
| Variable_name                  | Value                                            |
+--------------------------------+--------------------------------------------------+
| Innodb_buffer_pool_dump_status | Dumping of buffer pool not started               |
| Innodb_buffer_pool_load_status | Buffer pool(s) load completed at 260602  1:10:16 |
+--------------------------------+--------------------------------------------------+
2 rows in set (0.00 sec)
```

`innodb_buffer_pool_dump_pct`는 운영에서 특히 중요하다. 이 값은 Buffer Pool 전체를 모두 dump/load할지, 일정 비율만 사용할지를 결정한다. 기본값과 적정값은 버전·환경에 따라 확인해야 하지만, 원칙은 명확하다. 재시작 직후 필요한 working set만 빠르게 올리는 것이 목적이지, Buffer Pool 전체를 기계적으로 복원하는 것이 목적은 아니다.

## 4. 수동 dump/load의 실행 경로

수동으로 Buffer Pool dump를 만들거나 load를 트리거할 수 있다. 운영에서는 다음 상황에서 유용하다.

- 재시작 전 애플리케이션 트래픽이 정상 상태이고, 현재 Buffer Pool이 대표적인 hot set을 담고 있을 때
- 계획 점검 직전에 최신 working set을 dump하고 싶을 때
- 시작 후 load 상태를 확인하거나, 필요 시 load를 중단하고 싶을 때

아래 예제는 테스트 컨테이너에서 실행 가능한 형태로 수동 dump와 load 트리거를 보여준다. 실제 운영 서버에서는 점검 창, I/O 여유, 권한, replication topology를 확인한 뒤 실행해야 한다.

```sql
SET GLOBAL innodb_buffer_pool_dump_now = ON;

SHOW STATUS
WHERE Variable_name = 'Innodb_buffer_pool_dump_status';

SET GLOBAL innodb_buffer_pool_load_abort = ON;
SET GLOBAL innodb_buffer_pool_load_now = ON;

SHOW STATUS
WHERE Variable_name = 'Innodb_buffer_pool_load_status';
```

실행 결과(MySQL 8.0.46):

```text
mysql> SET GLOBAL innodb_buffer_pool_dump_now = ON;

Query OK, 0 rows affected (0.00 sec)

mysql> SHOW STATUS
    -> WHERE Variable_name = 'Innodb_buffer_pool_dump_status';

+--------------------------------+--------------------------------------------------+
| Variable_name                  | Value                                            |
+--------------------------------+--------------------------------------------------+
| Innodb_buffer_pool_dump_status | Buffer pool(s) dump completed at 260602  1:10:22 |
+--------------------------------+--------------------------------------------------+
1 row in set (0.00 sec)

mysql> SET GLOBAL innodb_buffer_pool_load_abort = ON;

Query OK, 0 rows affected (0.00 sec)

mysql> SET GLOBAL innodb_buffer_pool_load_now = ON;

Query OK, 0 rows affected (0.00 sec)

mysql> SHOW STATUS
    -> WHERE Variable_name = 'Innodb_buffer_pool_load_status';

+--------------------------------+--------------------------------------------------+
| Variable_name                  | Value                                            |
+--------------------------------+--------------------------------------------------+
| Innodb_buffer_pool_load_status | Buffer pool(s) load completed at 260602  1:10:22 |
+--------------------------------+--------------------------------------------------+
1 row in set (0.00 sec)
```

수동 dump는 현재 Buffer Pool의 page id 목록을 저장한다. 수동 load는 dump 파일을 기반으로 page를 읽어온다. `load_abort`는 이미 진행 중인 load가 오래 걸리거나 서비스 시작 부하와 충돌한다고 판단될 때 사용할 수 있다. 다만 load 중단은 성능 안정화 전략을 포기한다는 뜻이므로, 단순히 상태 메시지가 오래 보인다는 이유만으로 습관적으로 중단해서는 안 된다.

## 5. 재시작 직후 성능 곡선을 어떻게 해석할 것인가

Buffer Pool warmup을 이해하려면 “시작 완료”와 “성능 정상화”를 구분해야 한다. MySQL이 TCP 연결을 받고 SQL을 실행할 수 있다고 해서 Buffer Pool이 업무 부하에 맞게 데워진 것은 아니다. 운영 점검에서 흔히 발생하는 오류는 MySQL process health만 보고 애플리케이션 트래픽을 즉시 전환하는 것이다.

재시작 후 성능은 대략 다음 단계로 나뉜다.

1. 서버 시작과 crash recovery 확인
2. Buffer Pool load 시작 또는 수동 warmup 수행
3. 핵심 read query의 지연 시간 안정화 확인
4. 복제 지연, connection 증가, storage read latency 확인
5. 트래픽 점진 전환

Buffer Pool dump/load는 2단계를 자동화하거나 단축한다. 그러나 3~5단계의 운영 확인을 대체하지 않는다. 특히 storage가 느린 환경, Buffer Pool이 매우 큰 환경, 또는 재시작 후 즉시 대량 read traffic이 유입되는 환경에서는 load가 진행 중인 동안 애플리케이션 query도 같은 storage를 읽으면서 경쟁할 수 있다.

운영 진단에서는 다음 지표를 함께 본다.

- `Innodb_buffer_pool_reads`: Buffer Pool miss로 인해 디스크에서 읽은 횟수
- `Innodb_buffer_pool_read_requests`: 논리 읽기 요청 수
- `Innodb_buffer_pool_pages_data`: data page 수
- `Innodb_buffer_pool_pages_dirty`: dirty page 수
- storage read latency와 read IOPS
- 애플리케이션 핵심 read query의 p95/p99 latency

다음 쿼리는 Buffer Pool read hit 관점의 상태 값을 간단히 확인하는 예다.

```sql
SHOW STATUS
WHERE Variable_name IN (
  'Innodb_buffer_pool_read_requests',
  'Innodb_buffer_pool_reads',
  'Innodb_buffer_pool_pages_data',
  'Innodb_buffer_pool_pages_dirty'
);
```

실행 결과(MySQL 8.0.46):

```text
mysql> SHOW STATUS
    -> WHERE Variable_name IN (
    ->   'Innodb_buffer_pool_read_requests',
    ->   'Innodb_buffer_pool_reads',
    ->   'Innodb_buffer_pool_pages_data',
    ->   'Innodb_buffer_pool_pages_dirty'
    -> );

+----------------------------------+-------+
| Variable_name                    | Value |
+----------------------------------+-------+
| Innodb_buffer_pool_pages_data    | 1148  |
| Innodb_buffer_pool_pages_dirty   | 0     |
| Innodb_buffer_pool_read_requests | 15350 |
| Innodb_buffer_pool_reads         | 1002  |
+----------------------------------+-------+
4 rows in set (0.00 sec)
```

`Innodb_buffer_pool_reads` 자체가 증가한다고 해서 항상 문제는 아니다. workload가 커지면 물리 읽기는 자연스럽게 늘 수 있다. 중요한 것은 재시작 직후 평소보다 물리 읽기 비율이 급증하는지, 그 급증이 query latency와 storage latency 증가로 이어지는지다. 단일 숫자보다 시간대별 변화와 점검 시점의 baseline 비교가 중요하다.

## 6. 운영 전략: dump/load를 언제 켜고 어떻게 조정할까

대부분의 범용 MySQL 운영 환경에서는 `innodb_buffer_pool_dump_at_shutdown`과 `innodb_buffer_pool_load_at_startup`을 켜는 편이 유리하다. 특히 다음 조건에 해당하면 warmup의 가치가 크다.

- Buffer Pool 크기가 크고, 업무 working set이 비교적 반복적이다.
- 재시작 후 read latency spike가 반복적으로 관찰된다.
- storage read latency가 낮지 않거나 burst I/O 비용이 크다.
- primary 승격 또는 failover 이후 빠른 안정화가 중요하다.
- 점검 작업 뒤 애플리케이션 트래픽을 빠르게 복구해야 한다.

반대로 다음 상황에서는 보수적으로 조정해야 한다.

- 재시작 후 load 때문에 storage I/O가 과도하게 몰린다.
- 업무 패턴이 자주 바뀌어 이전 hot set이 현재 workload를 대표하지 못한다.
- Buffer Pool이 매우 크고 dump/load 대상 비율이 지나치게 높다.
- 점검 후 즉시 batch job이나 대량 scan이 실행되어 warmup 효과가 희석된다.

실무에서는 `innodb_buffer_pool_dump_pct`를 조정해 균형을 잡는다. 값이 너무 낮으면 필요한 hot page가 충분히 복원되지 않는다. 값이 너무 높으면 시작 시점의 load 비용이 커진다. 정답은 고정값이 아니라 “재시작 후 안정화 시간”, “storage read 부하”, “핵심 query latency”를 함께 보며 결정해야 한다.

## 7. Aurora MySQL에서의 해석

Aurora MySQL은 Community MySQL과 InnoDB 계층의 많은 개념을 공유하지만, storage 계층과 failover 방식이 다르다. Aurora는 분산 storage를 사용하고, instance 장애나 failover 시 compute node가 바뀔 수 있다. 이때 Buffer Pool은 instance-local memory이므로 새 writer 또는 reader instance에서 warm 상태가 그대로 보장되지 않는다.

Aurora 운영에서 중요한 차이는 다음과 같다.

- cluster volume은 유지되더라도 Buffer Pool은 DB instance 메모리에 종속된다.
- failover 후 새 writer가 기존 writer와 같은 cache 상태를 갖는다고 가정하면 안 된다.
- Performance Insights, CloudWatch 지표, Enhanced Monitoring을 함께 보고 failover 직후 read latency와 DB load 변화를 확인해야 한다.
- reader를 승격하는 구조에서는 평소 reader workload가 writer 승격 후 workload와 다를 수 있다. reader의 Buffer Pool이 writer 업무 hot set을 충분히 담고 있다고 단정할 수 없다.

따라서 Aurora에서도 재시작·failover 직후 성능 안정화 관점은 여전히 필요하다. 다만 Community MySQL의 로컬 파일 기반 dump/load만으로 모든 failover cache 문제를 해결한다고 기대해서는 안 된다. 애플리케이션 connection 재시도, 트래픽 점진 전환, read/write endpoint 동작, 복제 지연, storage read latency를 함께 보는 runbook이 필요하다.

## 8. 흔한 오해와 장애 모드

### 8.1 dump 파일을 백업으로 오해하는 경우

Buffer Pool dump 파일은 page id 목록이다. 데이터 백업이 아니며, 장애 복구의 핵심 파일도 아니다. backup/recovery는 physical backup, logical dump, binary log, point-in-time recovery 체계로 설계해야 한다.

### 8.2 load가 끝나면 모든 query가 빨라진다고 믿는 경우

dump/load는 이전 hot page 일부를 올리는 기능이다. workload가 바뀌었거나, SQL이 대량 scan을 수행하거나, optimizer plan이 달라졌다면 warmup만으로 해결되지 않는다. 또한 page가 Buffer Pool에 있어도 CPU, lock, temporary table, sort, network 지연은 별개의 병목이다.

### 8.3 전체 Buffer Pool을 무조건 load하려는 경우

Buffer Pool이 크다고 해서 전체를 load하는 것이 항상 좋은 전략은 아니다. 시작 직후 storage I/O가 몰리면 애플리케이션 트래픽과 경쟁한다. `dump_pct`는 성능 안정화와 시작 부하 사이의 trade-off다.

### 8.4 재시작 직후 지표를 평상시와 직접 비교하는 경우

cold cache 구간은 특수한 시간대다. 이때의 물리 읽기와 latency를 평상시 평균과 단순 비교하면 과장된 경보가 발생할 수 있다. 점검 runbook에는 “재시작 후 N분 동안 관찰할 지표”와 “트래픽 전환 기준”을 별도로 둬야 한다.

## 9. 운영 점검표

재시작 전에는 다음을 확인한다.

- [ ] 현재 workload가 대표적인 정상 상태인지 확인한다.
- [ ] `innodb_buffer_pool_dump_at_shutdown`, `innodb_buffer_pool_load_at_startup`, `innodb_buffer_pool_dump_pct` 값을 확인한다.
- [ ] 계획 재시작이라면 필요 시 `SET GLOBAL innodb_buffer_pool_dump_now = ON`으로 최신 hot set을 저장한다.
- [ ] storage read IOPS와 latency baseline을 기록한다.
- [ ] 핵심 read query의 p95/p99 latency baseline을 기록한다.

재시작 직후에는 다음을 확인한다.

- [ ] MySQL start와 recovery가 완료되었는지 확인한다.
- [ ] `Innodb_buffer_pool_load_status`로 load 상태를 확인한다.
- [ ] `Innodb_buffer_pool_reads` 증가 속도와 storage read latency를 관찰한다.
- [ ] 애플리케이션 트래픽을 한 번에 모두 전환하지 않고 점진적으로 늘린다.
- [ ] query latency, connection 수, replication 지연, error log를 함께 본다.

사후에는 다음을 정리한다.

- [ ] 재시작 후 성능 안정화까지 걸린 시간을 기록한다.
- [ ] dump/load 설정이 적절했는지 평가한다.
- [ ] `dump_pct` 조정 필요성을 검토한다.
- [ ] Aurora 환경이라면 failover 대상 instance의 workload와 cache 상태를 별도로 분석한다.

## 10. 결론

Buffer Pool warmup은 MySQL 재시작 직후의 성능 리스크를 줄이는 기본 운영 기술이다. 핵심은 Buffer Pool의 데이터를 저장하는 것이 아니라, 이전에 중요했던 page의 위치 정보를 저장하고 시작 후 다시 읽어 cache miss 구간을 줄인다는 점이다. 따라서 dump/load는 backup도 아니고 완전한 성능 보장 장치도 아니다. 그러나 계획 점검, 장애 복구, failover 이후 안정화 시간을 줄이는 데 실질적인 도움이 된다.

운영자는 `dump_at_shutdown`, `load_at_startup`, `dump_pct`, 수동 dump/load 상태를 이해하고, 재시작 직후의 storage I/O와 query latency를 함께 관찰해야 한다. 다음 글에서는 InnoDB의 checkpoint와 dirty page flush가 재시작 시간, write 성능, crash recovery와 어떻게 연결되는지 살펴볼 수 있다.
