Como Otimizar MySQL my.cnf em VPS Pequena (1-2 GB RAM) sem Travar
Aprenda a otimizar MySQL my.cnf em VPS pequena: ajustar InnoDB buffer pool, desligar performance_schema e reduzir RAM sem perder throughput.
VPS de 1 ou 2 GB de RAM é o ponto onde MySQL com defaults começa a doer.
O processo mysqld ocupa ~450 MB no boot, sua aplicação PHP/Node fica
apertada, o kernel começa a matar processos por OOM e o swap entra em
ação destruindo o I/O. O problema raramente é o MySQL em si — é o
my.cnf padrão, calibrado pra um servidor genérico de 8 GB.
Este tutorial cobre os ajustes de my.cnf que realmente importam em VPS
pequena: dimensionar innodb_buffer_pool_size pra realidade da máquina,
desligar performance_schema quando faz sentido, controlar conexões e
log binário, e validar tudo com comandos que você roda antes e depois.
A persona é developer que subiu MySQL 8 ou MariaDB num droplet de 1-2 GB,
viu o mysqld consumir 40% da RAM e quer reduzir sem perder performance.
Tempo de execução: 20-30 minutos incluindo backup do my.cnf original,
edição, restart e medição. Os ajustes valem pra MySQL 8.0+ e MariaDB
10.6+ em Ubuntu 22.04/24.04 LTS e Debian 12.
Pré-requisitos
VPS Linux (Ubuntu 22.04/24.04 LTS ou Debian 12) com 1 ou 2 GB de RAM,
MySQL 8.0+ ou MariaDB 10.6+ instalado e rodando, acesso sudo e
credenciais do root do MySQL. Faça um backup do banco antes —
mysqldump --single-transaction --all-databases > backup.sql — porque
restart com my.cnf quebrado pode impedir o serviço de subir.
Confirme o que você tem hoje antes de mexer em qualquer linha:
free -m ps -o rss= -p $(pidof mysqld) mysql --version /etc/mysql/mysql.conf.d/mysqld.cnf Em MariaDB, o arquivo principal é /etc/mysql/mariadb.conf.d/50-server.cnf.
Em ambos, a regra é a mesma: não edite /etc/mysql/my.cnf diretamente —
ele só faz !includedir dos arquivos nas pastas mysql.conf.d/ ou
mariadb.conf.d/.
Diagnóstico do consumo atual
Antes de cortar, meça. Sem baseline, você não sabe se o ajuste melhorou.
Veja o RSS atual do mysqld e quanto isso representa da RAM:
ps -o pid,rss,cmd -p $(pidof mysqld)
free -mO valor de rss está em KB. Divida por 1024 pra ter MB. Em VPS de 1 GB
com MySQL 8 default, espere ver algo entre 380 e 500 MB — bem acima do
necessário pra carga real de um site pequeno.
Veja o uso real do InnoDB buffer pool — se o pool default de 128 MB está sobrando ou faltando:
mysql -u root -p -e "SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_pages%';"O que interpretar:
pages_total= tamanho do pool em páginas de 16 KBpages_freepróximo de zero = pool cheio, MySQL está reciclando páginaspages_data/pages_total= quanto está em uso útil
Se pages_free é alto (>30% do total) e o servidor tem dias de uptime,
você pode reduzir o pool sem prejuízo. Se está próximo de zero e
Innodb_buffer_pool_reads (não read_requests) cresce rápido, o pool
está subdimensionado.
Cheque o performance_schema — ele sozinho come 70-100 MB:
mysql -u root -p -e "SELECT SUM(MEMORY_USED)/1024/1024 AS mb FROM sys.x\$memory_global_by_current_bytes;"Em VPS de 1 GB sem ferramenta de profiling externa lendo dele, é o primeiro candidato a desligar.
Editando o my.cnf
Crie um arquivo próprio de override em vez de mexer no mysqld.cnf
padrão — assim, atualizações de pacote não sobrescrevem seus ajustes.
Crie o arquivo de override:
sudo nano /etc/mysql/mysql.conf.d/99-hostini-tuning.cnfEm MariaDB: /etc/mysql/mariadb.conf.d/99-hostini-tuning.cnf. O número
99 garante que esse arquivo é lido por último — sobrescreve qualquer
default.
Cole esta configuração base pra VPS de 1 GB de RAM:
[mysqld]
# InnoDB — coração do MySQL
innodb_buffer_pool_size = 256M
innodb_buffer_pool_instances = 1
innodb_log_buffer_size = 8M
innodb_flush_method = O_DIRECT
innodb_flush_log_at_trx_commit = 2
# Conexões — VPS pequena não aguenta 150
max_connections = 50
thread_cache_size = 8
table_open_cache = 200
table_definition_cache = 400
# Performance schema — desligado em 1 GB
performance_schema = OFF
# Binary log — desligado se NÃO usa replicação
disable_log_bin
# Pra MariaDB use: skip-log-bin
# Logs lentos pra diagnóstico
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 2
# Temporários — em RAM até esse limite
tmp_table_size = 16M
max_heap_table_size = 16M
# Sort/join buffers — por conexão, cuidado com max_connections
sort_buffer_size = 256K
join_buffer_size = 256K
read_buffer_size = 128K
read_rnd_buffer_size = 256KPra VPS de 2 GB, ajuste só estas linhas:
innodb_buffer_pool_size = 512M
max_connections = 100
performance_schema = ON
performance-schema-instrument='memory/%=COUNTED'sort_buffer_size e join_buffer_size são alocados POR CONEXÃO ATIVA,
não globalmente. Subir cada um pra 4 MB com 100 conexões = 400 MB
potenciais só nesses buffers. Os valores baixos do snippet (256K) são
intencionais — query slow em VPS pequena resolve com índice, não com
buffer maior.
Salve (Ctrl+O, Enter, Ctrl+X) e valide a sintaxe antes do restart:
sudo mysqld --validate-configSe aparecer qualquer erro, o serviço não vai subir depois do restart. Corrija antes de continuar. Saída esperada: nenhuma linha (silêncio é sucesso).
Reinicie o MySQL e cheque o status:
sudo systemctl restart mysql
sudo systemctl status mysql --no-pagerEm MariaDB: sudo systemctl restart mariadb. Se o status mostra
active (running), prossegue. Se falhou, leia o motivo em
sudo journalctl -u mysql -n 50 — quase sempre é typo no .cnf.
Verificação
Confirma que os ajustes aplicaram e a economia de RAM apareceu.
Confirme os valores que entraram em vigor:
mysql -u root -p -e "SHOW VARIABLES WHERE Variable_name IN ('innodb_buffer_pool_size', 'max_connections', 'performance_schema', 'log_bin', 'tmp_table_size');"Os valores devem bater com o que você colocou no 99-hostini-tuning.cnf.
Se algum mostra o default antigo, o arquivo não está sendo lido — confira
o caminho e as permissões (precisa ser 644 root:root).
Meça o consumo de RAM novamente:
ps -o pid,rss,cmd -p $(pidof mysqld)
free -mExpectativa pós-ajuste em VPS de 1 GB: mysqld em ~280-340 MB (queda
de ~30%). Em 2 GB com performance_schema ligado: ~500-580 MB. Espere
alguns minutos com tráfego real antes da medição final — o pool aquece
e estabiliza.
Rode SHOW STATUS depois de 1-2 horas de uso real e confirme que o buffer pool não está sufocando:
mysql -u root -p -e "SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_%';"Sinais de saúde: pages_free > 5% do pages_total, reads crescendo
devagar comparado a read_requests (razão de hit > 99%). Se reads
explode, suba o buffer pool em 64 MB e reteste.
Resolução de problemas
MySQL não sobe após restart
Cheque o log do journal e identifique a linha exata que quebrou:
sudo journalctl -u mysql -n 80 --no-pager
Causas comuns: innodb_buffer_pool_size maior que a RAM total disponível,
O_DIRECT em filesystem que não suporta (raro em ext4/xfs), opção
deprecada em MySQL 8 (query_cache_size foi removido). Reverta seu
99-hostini-tuning.cnf pra base mínima (só innodb_buffer_pool_size)
e adicione linha por linha.
”Out of memory” no aplicativo após ajuste
Você reduziu a RAM do MySQL mas o app cresceu pra preencher. Rode
free -m durante carga real e veja se available cai abaixo de 100 MB.
Se sim, considere swappiness mais baixo (sudo sysctl vm.swappiness=10)
e ative um arquivo de swap de 1 GB como rede de proteção — não é solução
de produção, mas evita OOM kill enquanto você dimensiona melhor.
Queries que antes eram rápidas ficaram lentas
Sintoma típico de buffer pool pequeno demais — antes a tabela cabia em
RAM, agora não. Cheque Innodb_buffer_pool_reads (não read_requests)
no SHOW GLOBAL STATUS antes e depois. Se subiu drasticamente, aumente
innodb_buffer_pool_size em 64 MB e meça de novo. Solução estrutural:
adicionar índice na query, não inflar o pool.
Próximos passos
Com o my.cnf ajustado, vale a pena consolidar a operação:
- Configure rotação de logs lentos (
slow.logcresce rápido) vialogrotateem/etc/logrotate.d/mysql-server - Agende
mysqldump --single-transactiondiário comcrone envie pra storage externa (rclone + S3 ou Backblaze B2) - Em produção com replicação ou point-in-time recovery, mantenha
log_binligado e ajusteexpire_logs_days = 7pra controlar disco - Considere subir pra uma VPS com mais RAM se o pool de 256 MB não dá vazão — em geral, o salto pra 4 GB elimina ajuste fino e libera você pra focar no produto
A VPS Hostini já vem com SSD NVMe e kernel ajustado pra workloads de
banco — O_DIRECT funciona sem fallback silencioso e o I/O previsível
reduz a necessidade de buffer pool gigante pra compensar latência de
disco lento.
Perguntas frequentes
Quanta RAM o MySQL 8 consome no default sem ajuste?
Numa instalação padrão do MySQL 8.0 no Ubuntu/Debian, o processo mysqld ocupa entre 380 e 500 MB de RSS já no boot, sem nenhuma conexão ativa. Isso vem principalmente do innodb_buffer_pool_size (128 MB), performance_schema (~80 MB) e tabelas mysql.* do sistema. Em VPS de 1 GB, isso já consome ~40% da RAM antes de qualquer query.
Posso desligar o performance_schema sem quebrar nada?
Sim, com ressalvas. O performance_schema alimenta as views sys.* e ferramentas como percona-toolkit pt-query-digest. Desligar economiza 70-100 MB de RAM mas você perde visibilidade fina de queries lentas. Recomendado em VPS de 1 GB; em 2 GB ou mais, deixe ligado e ajuste só os consumers via setup_consumers.
Qual o valor ideal pra innodb_buffer_pool_size em VPS pequena?
A regra de 70-80% da RAM física só vale em servidores dedicados a MySQL. Em VPS de 1 GB rodando MySQL + app web + nginx, deixe entre 256 e 384 MB. Em VPS de 2 GB, 512 a 768 MB. O resto vai pra app, OS cache e margem contra OOM killer.
Vale a pena desligar o binary log (log_bin) em VPS pequena?
Só desligue se você NÃO usa replicação nem point-in-time recovery. O binary log consome IOPS (escrita sequencial) e disco (~10-20% do tráfego de escrita). Sem ele, o restore só volta ao último mysqldump. Pra single-instance com backup diário aceitável, desligar é OK; pra qualquer setup que possa virar replica depois, mantenha.
Como saber se meus ajustes funcionaram?
Rode SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_pages%' depois de 24h de uso real. Se Innodb_buffer_pool_pages_free fica próximo de zero e Innodb_buffer_pool_reads cresce rápido, o pool está pequeno. Combine com free -m pra confirmar que o sistema não está em swap. RSS do mysqld em ps aux deve ficar estável após warm-up.
Posso usar MariaDB no lugar do MySQL pra economizar RAM?
MariaDB 10.6+ tem footprint similar ao MySQL 8.0 — não há economia mágica. A diferença real vem do ajuste do my.cnf, não do fork. MariaDB tem alguns defaults mais conservadores (innodb_buffer_pool_size=128M também), então os mesmos ajustes deste tutorial valem com `[mariadb]` no lugar de `[mysqld]` quando aplicável.