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

O que você precisa antes de começar

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:

RAM total free -m
RAM mysqld ps -o rss= -p $(pidof mysqld)
Versão MySQL mysql --version
Caminho config /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.

01

Veja o RSS atual do mysqld e quanto isso representa da RAM:

ps -o pid,rss,cmd -p $(pidof mysqld)
free -m

O 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.

02

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 KB
  • pages_free próximo de zero = pool cheio, MySQL está reciclando páginas
  • pages_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.

03

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.

01

Crie o arquivo de override:

sudo nano /etc/mysql/mysql.conf.d/99-hostini-tuning.cnf

Em MariaDB: /etc/mysql/mariadb.conf.d/99-hostini-tuning.cnf. O número 99 garante que esse arquivo é lido por último — sobrescreve qualquer default.

02

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 = 256K

Pra VPS de 2 GB, ajuste só estas linhas:

innodb_buffer_pool_size = 512M
max_connections = 100
performance_schema = ON
performance-schema-instrument='memory/%=COUNTED'
Cuidado com buffers por conexão

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.

03

Salve (Ctrl+O, Enter, Ctrl+X) e valide a sintaxe antes do restart:

sudo mysqld --validate-config

Se 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).

04

Reinicie o MySQL e cheque o status:

sudo systemctl restart mysql
sudo systemctl status mysql --no-pager

Em 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.

01

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).

02

Meça o consumo de RAM novamente:

ps -o pid,rss,cmd -p $(pidof mysqld)
free -m

Expectativa 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.

03

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.log cresce rápido) via logrotate em /etc/logrotate.d/mysql-server
  • Agende mysqldump --single-transaction diário com cron e envie pra storage externa (rclone + S3 ou Backblaze B2)
  • Em produção com replicação ou point-in-time recovery, mantenha log_bin ligado e ajuste expire_logs_days = 7 pra 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.

Tópicos:
Próximos passos Cloud Ryzen com NVMe e proteção DDoS sempre ativa.Coloque em produção numa VPS Hostini →
Esse tutorial foi útil?
Falar no WhatsApp