Buffer Pool no MySQL: O Que Ninguém Te Conta Sobre Dimensionamento.
"70 a 80% da RAM" é o ponto de partida que todo mundo cita e quase ninguém termina de calcular. O resto da história é o que realmente evita incidente.
Diário de bordo, DBA sênior, estardalhaço nº 64.
Se você já leu qualquer guia de tuning de MySQL — inclusive o nosso — provavelmente já leu a mesma frase: "configure innodb_buffer_pool_size entre 70% e 80% da RAM disponível". É um bom ponto de partida, e está longe de ser errado. O problema é que é onde a maioria das explicações para — como se o resto do porão de carga se organizasse sozinho depois disso.
Buffer pool é a memória onde o InnoDB mantém páginas de dados e índice em cache, para não precisar ir ao disco a cada leitura. É, sem exagero, o parâmetro de maior impacto isolado em qualquer instância MySQL. Mas dimensionar bem não é escolher um número e esquecer — é entender hit ratio, como o MySQL decide o que manter quente e o que descartar, o que acontece quando você erra para cima (spoiler: pior que errar para baixo), e como sobreviver a um restart sem que a instância volte lenta por horas enquanto reconstrói o cache do zero. Este é o guia que normalmente fica de fora dos artigos de "70-80% da RAM e pronto" — e que faz parte de todo Health Check de banco de dados que conduzimos.
01
O QUE O BUFFER POOL REALMENTE GUARDA — E POR QUE "70-80% DA RAM" É SÓ A LARGADA
O buffer pool guarda páginas de 16 KB (tamanho padrão) contendo linhas de tabela e entradas de índice — não guarda "tabelas inteiras" como uma unidade, guarda páginas individuais, cada uma podendo pertencer a qualquer tabela ou índice do banco. Quando uma query precisa de um dado, o InnoDB primeiro verifica se a página já está no buffer pool. Se estiver, é leitura em memória — nanosegundos. Se não estiver, é uma ida ao disco — mesmo em SSD NVMe, ordens de magnitude mais lenta.
A regra dos 70-80% da RAM existe porque o restante da memória precisa sobrar para: conexões (thread stack, sort buffer, join buffer por sessão), o sistema operacional, e qualquer outro processo rodando no host. Mas essa fatia é um teto de segurança genérico — o número certo vem de medir o working set real da aplicação: o volume de dados efetivamente acessado com frequência. Um banco de 500 GB pode ter um working set de 40 GB se a maior parte do histórico raramente é lida — e nesse caso, um buffer pool de 64 GB já cobre o que importa, mesmo estando bem abaixo de "70-80% de um servidor com 512 GB de RAM".
-- Tamanho atual do buffer pool SHOW VARIABLES LIKE 'innodb_buffer_pool_size'; -- Redimensionar online, sem restart (MySQL 5.7.5+, mais estável a partir do 8.0) SET GLOBAL innodb_buffer_pool_size = 68719476736; -- 64 GB
FERRAMENTA INTERATIVA
Calculadora de innodb_buffer_pool_size.
Estimativa inicial baseada em RAM disponível, tipo de ambiente, concorrência e working set. Ponto de partida — não substitui medir hit ratio sob carga real.
Recomendação
29 GB
≈ 89% da RAM total
innodb_buffer_pool_instances
4
exige restart para alterar
Reservado (SO + conexões)
3.2 GB
SO 2.0 GB · conexões 1.2 GB
- ⚠ Recomendação acima de 85% da RAM. Confirme se sobra memória real para picos de conexão e outros processos do host.
SET GLOBAL innodb_buffer_pool_size = 30601641984; -- 29 GB -- innodb_buffer_pool_instances = 4 (exige restart; ajustar no my.cnf / parameter group)
Exportar para compartilhar
Inclui inputs, recomendação, alertas contextuais e comandos prontos — pronto para anexar ao ticket.
Comandos prontos para os próximos passos
Selecionados a partir das suas escolhas (servidor dedicado, 200 conexões, working set não informado). Execute na mesma ordem para validar o impacto da mudança.
SQL1. Hit ratio do buffer pool (meta ≥ 99,9% em OLTP)
SELECT
ROUND(
(1 - (
SELECT VARIABLE_VALUE FROM performance_schema.global_status
WHERE VARIABLE_NAME = 'Innodb_buffer_pool_reads'
) / NULLIF((
SELECT VARIABLE_VALUE FROM performance_schema.global_status
WHERE VARIABLE_NAME = 'Innodb_buffer_pool_read_requests'
), 0)) * 100,
4) AS hit_ratio_pct;Rode antes e depois de aplicar o novo tamanho. Queda abaixo de 99% indica working set maior que o buffer pool.
SQL2. Estado atual do buffer pool
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_%'; SHOW GLOBAL VARIABLES LIKE 'innodb_buffer_pool%';
Compare pages_data, pages_free e pages_dirty ao longo do dia — pool saudável tem pages_free próximo de zero em regime.
SQL3. Diagnóstico completo do InnoDB (LRU, flush, latches)
SHOW ENGINE INNODB STATUS\G
Foque nas seções BUFFER POOL AND MEMORY (Free buffers, Modified db pages, LRU len) e LATEST DETECTED DEADLOCK.
SQL4. Estimar o working set real (dados + índices ativos)
SELECT
table_schema,
ROUND(SUM(data_length + index_length) / 1024 / 1024 / 1024, 2) AS size_gb
FROM information_schema.tables
WHERE table_schema NOT IN ('mysql','information_schema','performance_schema','sys')
GROUP BY table_schema
ORDER BY size_gb DESC;Aproximação por schema. Working set real ≈ tabelas quentes + índices tocados nas últimas 24h — use com SHOW TABLE STATUS e performance_schema.table_io_waits_summary_by_table.
SQL5. EXPLAIN ANALYZE em uma query representativa
-- Substitua pela sua query mais crítica EXPLAIN ANALYZE SELECT /* sua query aqui */ * FROM sua_tabela WHERE coluna_indexada = ? LIMIT 100;
Rode antes e depois da mudança. Aprofunde a leitura em: "Como Ler um EXPLAIN do MySQL de Verdade" (link no cluster).
SQL6. Confirmar pico real de conexões (input: 200)
SHOW GLOBAL STATUS LIKE 'Max_used_connections'; SHOW GLOBAL STATUS LIKE 'Max_used_connections_time'; SHOW GLOBAL STATUS LIKE 'Threads_connected';
Se Max_used_connections for maior que o valor informado, refaça o cálculo com o pico real.
$7. Checagem de swap e pressão de memória no host
# Uso de swap acontecendo agora? si/so > 0 é sinal de alerta
vmstat 1 5
# Estado geral da memória
grep -E 'MemTotal|MemFree|SwapTotal|SwapFree|Buffers|Cached' /proc/meminfo
# Risco de OOM para o processo mysqld
pidof mysqld | xargs -I{} cat /proc/{}/oom_scoreQualquer swap ativo com MySQL é sinal para reduzir buffer pool — swap de página quente é pior que ler do datafile.
Próximos passos de verificação
- Aplicar o valor em janela de baixa carga e monitorar por pelo menos 24h em produção real — revisar antes o checklist final de dimensionamento.
- Medir
hit_ratio_pctna seção 02 — Hit ratio sob carga de pico — meta prática ≥ 99,9% em OLTP. - Acompanhar no SO:
si/soemvmstat,SwapTotal/SwapFreeem/proc/meminfoeoom_scoredo processo mysqld — contexto na seção 04 — dimensionar demais e swap. - Revisar
innodb_redo_log_capacityem conjunto — buffer pool grande com redo log subdimensionado gera picos de flush (ver seção 06 — dirty pages e checkpoint). - Repetir a medição após 30 dias — working set cresce com o dado; a foto de hoje envelhece. Após restart, planeje o warm-up (seção 07).
Verificações relacionadas no artigo
- → Por que sugerimos
4instances: seção 03 — innodb_buffer_pool_instances. - → Recomendação acima de 85% da RAM: leia seção 04 — o erro de dimensionar demais antes de aplicar.
- → Você deixou o working set em 0. Comece medindo pelo hit ratio (seção 02) para calibrar o valor.
- → Em dúvida se vale ajustar sozinho: quando chamar um DBA especialista.
02
HIT RATIO — A MÉTRICA QUE DECIDE SE O NÚMERO ESTÁ CERTO
O tamanho do buffer pool só tem um juiz confiável: o hit ratio medido sob carga real, não em horário de baixo tráfego.
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;- Acima de 99,9%: o working set cabe confortavelmente em memória. RAM ociosa aqui não é desperdício — é margem de segurança para crescimento.
- Entre 99% e 99,9% em workload OLTP: zona de atenção. Vale acompanhar a tendência ao longo de semanas antes de decidir aumentar.
- Abaixo de 99%: o working set não cabe em memória. Cada ponto percentual perdido aqui significa mais leituras físicas de disco, e o efeito é sentido primeiro em latência de cauda (p95, p99), não na média — o que costuma atrasar a detecção do problema.
Medir uma vez não basta. Hit ratio é uma foto — o comportamento muda com pico de fim de mês, campanha de marketing, ou crescimento orgânico de dado ao longo dos meses. Faz parte de qualquer rotina saudável de operação acompanhar essa métrica continuamente, não só quando alguém reclama de lentidão.
03
INNODB_BUFFER_POOL_INSTANCES — DIVIDINDO O PORÃO PARA REDUZIR FILA NA ESCOTILHA
Em servidores com muita RAM (tipicamente acima de 64 GB dedicados ao buffer pool), um único buffer pool monolítico vira ponto de contenção: múltiplas threads competindo pelo mesmo mutex interno para ler e escrever páginas, mesmo em operações não relacionadas entre si.
innodb_buffer_pool_instances divide o buffer pool em pedaços independentes, cada um com seu próprio mutex — como dividir o porão de carga em compartimentos separados, cada um com sua própria escotilha, em vez de uma fila única para acessar tudo.
SHOW VARIABLES LIKE 'innodb_buffer_pool_instances';
- Buffer pool até 8 GB: 1 instância já é suficiente — dividir demais aqui só fragmenta memória sem ganho real.
- Buffer pool entre 8 GB e 64 GB: 4 a 8 instâncias é o intervalo prático mais comum.
- Buffer pool acima de 64 GB: 8 a 16 instâncias, ajustado por teste de carga — mais que isso raramente compensa e pode fragmentar demais o cache.
Esse parâmetro exige restart para ser alterado — diferente do tamanho total do buffer pool, que pode ser redimensionado online. Planeje a janela de manutenção quando decidir mudá-lo.
04
O ERRO DE DIMENSIONAR DEMAIS — QUANDO "MAIOR É MELHOR" VIRA EJETAR CARGA NO VÁCUO
A intuição mais comum é: "tenho RAM sobrando, então aumento o buffer pool o máximo possível". Esse raciocínio ignora que o buffer pool não é o único consumidor de memória da instância — e que passar do limite tem uma consequência muito pior do que um hit ratio abaixo do ideal.
Cada conexão ativa consome memória própria: sort buffer, join buffer, thread stack, read buffer. Em picos de concorrência, isso soma gigabytes adicionais, fora do buffer pool. Se o buffer pool foi dimensionado sem essa margem, o sistema operacional começa a usar swap para compensar — e swap em banco de dados não é "um pouco mais lento", é catastrófico: o sistema operacional pode escolher justamente páginas quentes do buffer pool para mandar para o disco de swap, e a mesma leitura que era rápida em memória vira mais lenta que se tivesse ido direto ao datafile original.
-- Sinais de pressão de memória a acompanhar no sistema operacional -- (fora do MySQL, mas essencial monitorar em conjunto) -- vmstat 1 → coluna "si"/"so" (swap in/out) deve ficar em zero, sempre -- free -h → "available" precisa ter folga real, não só "free"
Regra prática: nunca dimensione o buffer pool assumindo 100% da RAM livre. Reserve margem explícita para conexões no pico real medido (não no teórico de max_connections), para o sistema operacional, e para qualquer outro processo no host — backup, agente de monitoramento, replicação. Ejetar carga no vácuo espacial é reversível na ficção; swap em produção custa incidente de verdade.
DIAGNÓSTICO COMPLETO
🔍 MySQL Health Check.
Auditoria de buffer pool, hit ratio, redo log e uso real de memória sob carga — entregue em até 5 dias úteis com plano de ação priorizado por risco de incidente.
Solicitar Health Check →05
A LISTA LRU — POR QUE UM SELECT * GIGANTE PODE EXPULSAR TUDO QUE IMPORTA
O InnoDB não trata todas as páginas do buffer pool como igualmente "recentes". Ele usa uma lista LRU (Least Recently Used) dividida em duas partes: um sublist "young" (dados quentes, acessados com frequência) e um sublist "old" (dados recém-chegados ou pouco acessados). Uma página nova entra primeiro no sublist "old" e só é promovida ao "young" se for acessada de novo depois de um intervalo mínimo de tempo.
Esse desenho existe justamente para resolver um problema real: sem ele, uma única query de varredura grande — um relatório, um SELECT * sem filtro, um job de exportação em lote — traria milhares de páginas novas para o buffer pool de uma vez, empurrando para fora dados quentes que a aplicação usa a cada segundo, só para servir uma consulta que roda uma vez por dia. É exatamente um dos padrões cobertos em Erros que Todo Desenvolvedor Comete ao Escrever Queries MySQL.
SHOW VARIABLES LIKE 'innodb_old_blocks_time'; -- tempo mínimo (ms) que uma página precisa esperar no sublist "old" -- antes de poder ser promovida ao "young" — default 1000ms, geralmente adequado SHOW VARIABLES LIKE 'innodb_old_blocks_pct'; -- percentual do buffer pool reservado ao sublist "old" — default 37%
Para ambientes com jobs de relatório pesados rodando contra o mesmo buffer pool da operação transacional, vale considerar isolar essa carga — réplica dedicada para leitura analítica é geralmente a solução mais robusta, evitando que uma varredura grande derrube o hit ratio de tudo mais.
06
DIRTY PAGES E CHECKPOINT — O PEDÁGIO DE ESCRITA QUE NINGUÉM VÊ NO DASHBOARD
Toda modificação de dado primeiro acontece na página em memória do buffer pool — a página fica marcada como "dirty" (suja) até ser efetivamente gravada em disco pelo processo de checkpoint. Buffer pool com proporção alta de páginas dirty significa mais trabalho de flush acumulado, e picos de flush podem competir com I/O de leitura normal, gerando latência intermitente sem causa óbvia no dashboard de CPU.
-- Proporção de páginas dirty no buffer pool SHOW STATUS LIKE 'Innodb_buffer_pool_pages_dirty'; SHOW STATUS LIKE 'Innodb_buffer_pool_pages_total'; -- Se dirty/total ultrapassa consistentemente innodb_max_dirty_pages_pct, -- o InnoDB acelera o flush de forma agressiva, competindo com I/O de query normal SHOW VARIABLES LIKE 'innodb_max_dirty_pages_pct';
Esse é um dos motivos pelos quais innodb_buffer_pool_size não pode ser dimensionado isoladamente — ele interage diretamente com innodb_log_file_size/innodb_redo_log_capacity (quanto redo log disponível antes de forçar checkpoint) e com a capacidade de I/O real do storage. Buffer pool grande com redo log pequeno é receita para picos de flush frequentes — os dois parâmetros precisam ser dimensionados juntos, não em isolamento, como cobrimos em Performance Tuning MySQL 8.4.
CONSULTORIA MYSQL
Picos de flush e latência intermitente sem causa óbvia?
Dimensionamento conjunto de buffer pool, redo log e I/O real do storage — com quem já viu esse mesmo padrão em mais de 1.000 servidores em produção.
Falar com um especialista →07
SOBREVIVENDO A UM RESTART — O WARM-UP QUE NINGUÉM PLANEJA
Um buffer pool de 128 GB totalmente aquecido responde queries em microssegundos. O mesmo buffer pool, segundos depois de um restart, está vazio — e cada query precisa ir ao disco até que os dados "esquentem" de novo naturalmente. Em bancos grandes, esse período de aquecimento pode levar de minutos a horas, dependendo do padrão de acesso, exatamente na janela mais frágil possível: logo depois de uma manutenção ou de um failover.
O MySQL resolve isso nativamente com dump e reload automático do conteúdo do buffer pool:
SHOW VARIABLES LIKE 'innodb_buffer_pool_dump_at_shutdown'; SHOW VARIABLES LIKE 'innodb_buffer_pool_load_at_startup'; -- ambos ON por default desde o MySQL 5.6 — confirme que continuam ativos -- Disparar manualmente antes de uma manutenção planejada SET GLOBAL innodb_buffer_pool_dump_now = ON; -- Acompanhar o progresso do reload após o restart SHOW STATUS LIKE 'Innodb_buffer_pool_load_status';
Com essas variáveis ativas, o MySQL grava um snapshot de quais páginas estavam em memória antes de desligar, e recarrega o mesmo conjunto ao subir de novo — sem esperar o tráfego natural reaquecer tudo do zero. É a diferença entre reiniciar os sistemas com a tripulação já posicionada ou esperar cada estação religar sozinha, uma de cada vez, enquanto a nave já está em operação.
08
CLOUD E CONTAINERS — QUANDO "A RAM DO HOST" NÃO É A RAM REAL
Em ambientes gerenciados (RDS, Aurora, Cloud SQL) e em containers, o cálculo de 70-80% muda de premissa. Instâncias RDS aplicam seus próprios defaults e limites via parameter group, calculados sobre a memória da instância como o provedor a enxerga, e nem sempre expõem controle direto sobre innodb_buffer_pool_instances. Em containers Docker/Kubernetes, o MySQL frequentemente enxerga a RAM total do host físico, não o limite de memória (cgroup) configurado no container — dimensionar innodb_buffer_pool_size pela RAM "visível" em vez do limite real do container é uma causa comum de OOM kill em produção, silenciosa até o exato momento em que derruba a instância.
# Dentro de um container, confirme o limite real de memória do cgroup cat /sys/fs/cgroup/memory.max # cgroup v2 cat /sys/fs/cgroup/memory/memory.limit_in_bytes # cgroup v1
Regra prática em cloud/containers: dimensione sempre pelo limite contratado/configurado explicitamente, nunca pela RAM total que o sistema operacional reporta — os dois números frequentemente divergem, e é justamente essa divergência que causa os incidentes mais difíceis de diagnosticar depois.
CHECKLIST FINAL — DIMENSIONAMENTO DE BUFFER POOL 2026
innodb_buffer_pool_sizecalculado a partir do working set real, não só do percentual genérico da RAM.- Hit ratio medido sob carga real (pico, não ocioso), alvo acima de 99,9%.
- Margem explícita reservada para conexões no pico real medido, sistema operacional e outros processos do host.
vmstat/freemonitorados para confirmar zero atividade de swap — sempre.innodb_buffer_pool_instancesdimensionado por faixa de tamanho, ajustado em janela de manutenção quando necessário.- Cargas de relatório/exportação pesadas isoladas em réplica dedicada, evitando poluir o LRU da operação transacional.
innodb_buffer_pool_sizeeinnodb_redo_log_capacity/innodb_log_file_sizedimensionados em conjunto, não isoladamente.innodb_buffer_pool_dump_at_shutdowneinnodb_buffer_pool_load_at_startupconfirmados como ON.- Em cloud/containers, dimensionamento feito pelo limite real de memória contratado/configurado, não pela RAM total visível ao sistema operacional.
QUANDO CHAMAR UM DBA ESPECIALISTA
Calcular um valor inicial de buffer pool qualquer time consegue fazer com este guia. O que normalmente exige um especialista é a combinação de variáveis interdependentes sob carga real: working set que muda de padrão ao longo do dia, réplicas com perfil de acesso diferente do primário, ambiente em cloud com limites que mudam a cada resize de instância, ou um incidente de swap que já aconteceu e precisa de causa raiz confirmada — não só de "aumentar a instância" como resposta genérica.
É esse tipo de dimensionamento fino que fazemos em todo Health Check de banco de dados da HTI, sempre em conjunto com o que já cobrimos em Como Ler um EXPLAIN do MySQL de Verdade — um buffer pool bem dimensionado não compensa uma query que devolve full table scan como plano padrão, e vice-versa. Os quatro pilares (query, índice, plano de execução, memória) precisam ser avaliados juntos para o ganho aparecer de verdade, incluindo o inventário revisado em Índices Demais no MySQL.
PRÓXIMO PASSO
Buffer pool bem dimensionado é a base — mas só entrega quando query, índice e plano também estão alinhados.
É esse conjunto que costuma diferenciar um ambiente estável de um ambiente que "funciona até o próximo pico".
PERGUNTAS FREQUENTES
A regra dos 70-80% da RAM está errada?
Não está errada — é um ponto de partida seguro para a maioria dos ambientes dedicados. O problema é tratá-la como resposta final. O valor correto depende do working set real (medido via hit ratio sob carga), da margem necessária para conexões e sistema operacional, e — em cloud/containers — do limite real de memória contratado, que pode ser bem diferente da RAM total visível ao sistema.
É melhor errar para mais ou para menos no tamanho do buffer pool?
Errar para menos custa mais leituras de disco e hit ratio mais baixo — ruim, mas previsível e reversível ao ajustar o parâmetro. Errar para mais, a ponto de gerar swap, é significativamente pior: o sistema operacional pode remover justamente páginas quentes do buffer pool para o disco de swap, tornando leituras que eram rápidas em memória mais lentas que uma leitura direta ao datafile original.
Preciso reiniciar o MySQL para aumentar o buffer pool?
Não, desde o MySQL 5.7.5 o redimensionamento de innodb_buffer_pool_size pode ser feito online via SET GLOBAL, e ficou mais estável a partir do MySQL 8.0/8.4. Já innodb_buffer_pool_instances exige restart para ser alterado — planeje esse em janela de manutenção.
O que é o warm-up do buffer pool e por que ele importa?
É o período após um restart em que o buffer pool está vazio e cada leitura precisa ir ao disco até que os dados voltem a ficar em cache pelo uso natural. Em bancos grandes, pode levar minutos a horas. innodb_buffer_pool_dump_at_shutdown e innodb_buffer_pool_load_at_startup (ambos ON por default desde o MySQL 5.6) resolvem isso automaticamente, recarregando o mesmo conjunto de páginas que estava quente antes do desligamento.
Em RDS/Aurora eu ainda preciso me preocupar com dimensionamento de buffer pool?
Sim, com uma ressalva: o valor é definido via parameter group, calculado sobre a memória da instância como o provedor a reporta, e alguns parâmetros de ajuste fino (como innodb_buffer_pool_instances) podem não estar disponíveis para alteração direta. O princípio de medir hit ratio sob carga real e reservar margem para conexões continua igualmente válido.
PERGUNTAS RELACIONADAS
PERGUNTA RELACIONADA
Como dimensionar buffer pool dentro de um container Docker sem OOM kill?
→ Buffer Pool MySQL em Docker — Dimensionamento Prático 2026
PERGUNTA RELACIONADA
Como interpretar de verdade o plano de execução do MySQL?
→ Como Ler um EXPLAIN do MySQL de Verdade
PERGUNTA RELACIONADA
Como identificar e remover índices que só custam recurso?
→ Índices Demais no MySQL — Guia Completo 2026
PERGUNTA RELACIONADA
Quais são os erros mais comuns em queries que derrubam performance?
→ Erros em Queries MySQL — Guia de Performance 2026
PERGUNTA RELACIONADA
Como configurar redo log e demais parâmetros junto com o buffer pool?
→ Performance Tuning MySQL 8.4 — Guia Completo 2026
PERGUNTA RELACIONADA
Vale a pena terceirizar a operação MySQL 24/7 com DBA remoto?
→ DBA Remoto MySQL 24×7 — Quando vale a pena terceirizar?
Continue lendo
- → Consultoria MySQL — visão completa do serviço
- → Como Ler um EXPLAIN do MySQL de Verdade — Guia Completo 2026
- → Buffer Pool MySQL em Docker — Dimensionamento Prático 2026
- → Índices Demais no MySQL — Guia Completo 2026
- → Erros que Todo Desenvolvedor Comete ao Escrever Queries MySQL
- → Performance Tuning MySQL 8.4 — Guia Completo 2026
- → Health Check de banco de dados