Buffer Pool no MySQL: como dimensionar corretamente (um caso real de análise de memória)
Recentemente enfrentei uma situação interessante em um ambiente MySQL.
O servidor possuía aproximadamente 296 GB de RAM, e o MySQL estava configurado com:
innodb_buffer_pool_size = 214 GBDurante uma análise de infraestrutura surgiu a seguinte pergunta:
“Esse servidor realmente precisa de toda essa memória ou podemos reduzir a RAM?”
Esse tipo de questionamento é comum em ambientes grandes, principalmente quando estamos falando de servidores com centenas de gigabytes de memória.
Mas antes de simplesmente reduzir memória ou alterar o buffer pool, precisamos entender como o banco realmente está utilizando esse cache.
Neste post vou mostrar como fiz essa análise na prática.
O que é o Buffer Pool
O InnoDB Buffer Pool é a principal área de cache do MySQL.
Ele armazena em memória:
- páginas de dados
- páginas de índices
- páginas modificadas (dirty pages)
- metadados internos do InnoDB
Sempre que uma query precisa acessar dados, o MySQL primeiro verifica se aquela página já está em memória.
Se estiver, a leitura ocorre diretamente no buffer pool.
Caso contrário, o InnoDB precisa buscar a página no disco.
Quanto mais leituras forem atendidas pela memória, melhor será a performance.
O erro mais comum ao dimensionar Buffer Pool
Uma recomendação muito comum é:
Configure o buffer pool com 70% ou 80% da RAM.
Essa regra pode ser um bom ponto de partida, mas não deve ser tratada como verdade absoluta.
O MySQL não usa memória apenas no buffer pool.
Outros componentes também consomem memória:
- conexões simultâneas
- sort buffers
- read buffers
- table cache
- performance_schema
- memória do sistema operacional
Por isso, o dimensionamento correto precisa considerar o comportamento real do ambiente.
Como analisar o uso real do Buffer Pool
Primeiro precisamos entender quanto do buffer pool está realmente ocupado.
Podemos consultar:
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_pages%';Essas métricas mostram:
Os indicadores principais são:
Innodb_buffer_pool_pages_totalInnodb_buffer_pool_pages_dataInnodb_buffer_pool_pages_freeInnodb_buffer_pool_pages_dirty
Como cada página do InnoDB possui 16 KB, é possível calcular facilmente o uso real da memória.
Outra métrica importante: Hit Ratio
Além da ocupação do cache, também precisamos analisar a eficiência do buffer pool.
Isso é feito através do Buffer Pool Hit Ratio.
Podemos consultar:
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_read%';Fórmula do hit ratio:
Hit Ratio = 1 - (Innodb_buffer_pool_reads / Innodb_buffer_pool_read_requests)Quanto maior esse valor, maior a quantidade de leituras atendidas pela memória.
Automatizando essa análise
Para facilitar essa análise, podemos usar a seguinte consulta:
SELECT
ROUND(
(
1 - (
(
SELECT VARIABLE_VALUE
FROM performance_schema.global_status
WHERE VARIABLE_NAME = 'Innodb_buffer_pool_reads'
) /
(
SELECT VARIABLE_VALUE
FROM performance_schema.global_status
WHERE VARIABLE_NAME = 'Innodb_buffer_pool_read_requests'
)
)
) * 100,
4
) AS hit_ratio_pct,
ROUND(
(
(
SELECT VARIABLE_VALUE
FROM performance_schema.global_status
WHERE VARIABLE_NAME = 'Innodb_buffer_pool_pages_data'
) /
(
SELECT VARIABLE_VALUE
FROM performance_schema.global_status
WHERE VARIABLE_NAME = 'Innodb_buffer_pool_pages_total'
)
) * 100,
2
) AS data_occupancy_pct,
ROUND(
(
(
SELECT VARIABLE_VALUE
FROM performance_schema.global_status
WHERE VARIABLE_NAME = 'Innodb_buffer_pool_pages_free'
) /
(
SELECT VARIABLE_VALUE
FROM performance_schema.global_status
WHERE VARIABLE_NAME = 'Innodb_buffer_pool_pages_total'
)
) * 100,
2
) AS free_pct;Essa consulta retorna três métricas importantes:
- eficiência do cache
- ocupação real do buffer pool
- percentual de páginas livres
Resultado do ambiente analisado
Ao executar essa consulta no ambiente em questão, obtivemos:
hit_ratio_pct : 99.9756
data_occupancy_pct : 98.59
free_pct : 1.39Interpretando esses números
Hit Ratio — 99.97%
Quase todas as leituras estão sendo atendidas pela memória.
Isso mostra que o buffer pool está extremamente eficiente.
Ocupação do Buffer Pool — 98.59%
Quase todo o buffer pool está ocupado com páginas de dados.
Isso indica que o banco realmente mantém um working set grande em memória.
Páginas livres — 1.39%
Existe pouca sobra de cache.
Isso indica que o buffer pool está sendo bem aproveitado.
Visualizando o cenário
Para entender melhor a relação entre memória e working set, podemos imaginar o ambiente da seguinte forma:
RAM TOTAL DO SERVIDOR
┌─────────────────────────────────────────────┐
│ │
│ 296 GB RAM │
│ │
│ ┌─────────────────────────────────────┐ │
│ │ │ │
│ │ BUFFER POOL (214 GB) │ │
│ │ │ │
│ │ ┌─────────────────────────────┐ │ │
│ │ │ │ │ │
│ │ │ WORKING SET (~200 GB) │ │ │
│ │ │ │ │ │
│ │ └─────────────────────────────┘ │ │
│ │ │ │
│ └─────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────┘Esse diagrama mostra que o banco realmente mantém um grande volume de dados ativos em memória.
Conclusão da análise
Ao cruzar essas três métricas, a conclusão foi clara:
- o buffer pool não estava superdimensionado
- o banco realmente utilizava cerca de 200 GB de dados ativos em memória
Portanto, reduzir drasticamente a memória do servidor poderia gerar:
- aumento de leituras em disco
- maior latência nas queries
- aumento de I/O
Dimensionamento recomendado
Considerando o working set observado e a margem necessária para o sistema operacional e conexões, um sizing seguro seria:
Servidor entre 240 GB e 256 GB de RAM.
Reduzir para 200 GB de RAM, por exemplo, seria arriscado.
Conclusão
O tamanho do buffer pool não deve ser definido apenas por uma porcentagem da memória.
A recomendação de 70% ou 80% pode ser um ponto de partida, mas não substitui uma análise real do ambiente.
Uma análise correta deve considerar:
- eficiência do cache
- ocupação real do buffer pool
- concorrência de conexões
- comportamento do sistema operacional
- working set do banco
Porque tuning de banco de dados não é sobre seguir regras fixas.
É sobre entender como o banco realmente está utilizando os recursos disponíveis
