Por que fazer gerenciamento do banco de dados MySQL?

Banco de Dados MySQL
Pedro Tebaldi Autor: Pedro Tebaldi PM do KeepGreenEdnilson Correa Revisão técnica: Ednilson Correa SRE
Publicado nov/2016Atualizado set/2026

O MySQL é um sistema de gerenciamento de banco de dados (SGBD) relacional, mantido pela Oracle e distribuído também em edição open source. Ele guarda registros em tabelas, controla permissões por usuário e responde a consultas escritas em SQL.

Gerenciar esse banco significa acompanhar números concretos: quanto do cache o servidor aproveita e quantas conexões estão abertas. Além disso, importa quantas linhas ele lê para devolver uma só.

Todos os valores deste artigo saíram de um laboratório em Docker, com MySQL 8.4.7 e uma tabela de 500 mil pedidos. A medição é de 1º de setembro de 2026, portanto nenhum número aqui é estimativa de mercado.

 

O que é o MySQL e o que ele faz como SGBD

O MySQL é o SGBD relacional que recebe comandos SQL e cuida do resto. Ele grava em disco, mantém os índices atualizados, isola transações concorrentes e devolve o resultado. A aplicação nunca abre o arquivo de dados: ela pede e o MySQL decide como buscar.

Internamente, quem executa esse trabalho é o InnoDB, motor de armazenamento padrão. Ele implementa transações ACID, bloqueia por linha em vez de por tabela e mantém um cache próprio na memória, o buffer pool. Esse cache, aliás, é o primeiro número a olhar quando alguém reclama de lentidão.

No modelo relacional o esquema é obrigatório: cada coluna tem tipo e cada chave estrangeira aponta para um registro que existe. Dessa forma, a normalização das tabelas deixa de ser recomendação e vira restrição que o próprio banco cobra.

Permissões também moram no SGBD, nunca só na aplicação. O MySQL concede e revoga privilégios por usuário, por base e até por coluna. Com isso, segurança da informação vira configuração verificável, em vez de promessa.

 

Quais versões do MySQL ainda recebem correção

Em setembro de 2026, duas séries recebem correção: a 8.4 LTS e a 9.7 LTS.

A Oracle moveu o MySQL 8.0 para Sustaining Support em 21 de abril de 2026, conforme o aviso oficial de fim de vida. O 5.7 já estava nessa condição desde outubro de 2023.

 

Versão Situação em setembro de 2026 Desde
Sem patchMySQL 5.7 Sustaining Support: sem correção nova, inclusive de segurança 25/10/2023
Sem patchMySQL 8.0 Sustaining Support: sem correção nova, inclusive de segurança 21/04/2026
AtivaMySQL 8.4 LTS Suporte ativo: alvo natural de migração de quem está na 8.0 04/2024
AtivaMySQL 9.7 LTS Suporte ativo: série LTS mais recente publicada pela Oracle 04/2026

 

Sustaining Support é suporte sem correção nova, inclusive de segurança. O servidor continua rodando, porém cada vulnerabilidade publicada depois dessa data fica sem patch oficial. Conferir a versão em produção, portanto, é a primeira tarefa de gerenciamento.

 

Quais métricas olhar e qual valor é ruim

A saúde do MySQL se lê em cinco números, todos disponíveis sem plugin nenhum. São eles: aproveitamento do buffer pool, conexões abertas, contador de queries lentas, razão entre linhas lidas e devolvidas, além do atraso da réplica. Cada um tem limiar próprio. É o limiar que transforma o número em decisão.

Comece pelo buffer pool hit ratio, que mede quanto o servidor respondeu da memória em vez do disco. A conta usa duas variáveis de status e cabe numa consulta só:




hit-ratio.sql
-- Quanto o MySQL respondeu da memoria, em vez de ir ao disco
SELECT ROUND(100 * (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')
)), 2) AS hit_ratio_pct;
 
+---------------+
| hit_ratio_pct |
+---------------+
|         99.95 |
+---------------+

No laboratório o valor ficou em 99,95%. Abaixo de 99% sob carga real, o buffer pool está pequeno para o conjunto de dados quente. O caminho, nesse caso, é aumentar innodb_buffer_pool_size.

 

Métrica Onde ler Limiar que pede ação
Buffer pool hit ratio Innodb_buffer_pool_reads dividido por Innodb_buffer_pool_read_requests Abaixo de 99%: o buffer pool não cobre o dado quente
Conexões abertas Threads_connected em SHOW GLOBAL STATUS Acima de 80% de max_connections, que vem em 151 por padrão
Queries lentas Slow_queries, com o log de query lenta ligado Qualquer crescimento constante por minuto em horário de pico
Linhas lidas por linha devolvida Rows_examined sobre Rows_sent, no log de query lenta Acima de 100 para 1: falta índice para aquele filtro
Atraso da réplica Seconds_Behind_Source em SHOW REPLICA STATUS Acima da janela de RPO combinada com o negócio

 

Esses mesmos alvos existem em outros bancos, com nomes diferentes. No monitoramento de Oracle Database, por exemplo, o equivalente do buffer pool vive dentro da SGA. O log de query lenta, por sua vez, dá lugar ao AWR.

Ferramentas prontas já aplicam esses limiares. No phpMyAdmin, por exemplo, a aba Status traz o Assessor, que lista cada aviso com o problema, a fórmula usada e o valor de corte:

 
Tela do Sistema de assessoria do phpMyAdmin 5.2.2 com o aviso de joins sem índice aberto, mostrando o problema, a recomendação, a fórmula que soma Select_range_check, Select_scan e Select_full_join dividida pelo Uptime, e o limiar usado no teste

 

Esse aviso de joins sem índice soma Select_range_check, Select_scan e Select_full_join, dividindo o total pelo uptime. No laboratório a média chegou a 31,85 varreduras por minuto, contra o limite de uma por hora que a ferramenta considera aceitável.

 

Como encontrar a query lenta que ninguém reportou

Nada disso exige ferramenta externa: o próprio MySQL registra as consultas demoradas, desde que o log esteja ligado. Três parâmetros bastam: o interruptor, o arquivo de destino e o limiar em segundos. Um quarto captura também as consultas rápidas que varrem a tabela inteira.




my.cnf
[mysqld]
slow_query_log                = ON
slow_query_log_file           = /var/lib/mysql/slow.log
# limiar em segundos: acima disso, a consulta e registrada
long_query_time               = 1
# registra tambem a consulta rapida que varre a tabela inteira
log_queries_not_using_indexes = ON

Com esse ajuste, o log passa a mostrar não só o que já dói, mas o que vai doer quando o volume crescer. A entrada gerada pelo laboratório saiu assim:




slow.log
# Time: 2026-09-01T22:54:25.200570Z
# User@Host: root[root] @ localhost []  Id:   289
# Query_time: 0.120595  Lock_time: 0.000001 Rows_sent: 25  Rows_examined: 500000
SET timestamp=1788303265;
SELECT id, valor, criado_em FROM pedidos
 WHERE cliente_id = 4242 AND status = 'pago';

A linha decisiva é a terceira. O servidor leu 500 mil linhas para devolver 25, ou seja, 20 mil linhas lidas por linha entregue. Acima de 100 para 1, a conclusão já é a mesma: falta índice para aquele filtro.

 

O índice antes e depois, com o tempo medido

Antes de pagar pela consulta, dá para ver o plano de execução com EXPLAIN. Sem índice nas colunas do filtro, o MySQL escolhe type=ALL, ou seja, a varredura completa da tabela:




explain-antes.sql
EXPLAIN SELECT id, valor, criado_em FROM pedidos
 WHERE cliente_id = 4242 AND status = 'pago';
 
+------+---------------+------+--------+----------+-------------+
| type | possible_keys | key  | rows   | filtered | Extra       |
+------+---------------+------+--------+----------+-------------+
| ALL  | NULL          | NULL | 500076 |     1.00 | Using where |
+------+---------------+------+--------+----------+-------------+
 
-- EXPLAIN ANALYZE executa de verdade e devolve o tempo gasto
-> Filter: ((pedidos.status = 'pago') and (pedidos.cliente_id = 4242))
     (cost=50673 rows=5001) (actual time=1.78..128 rows=25 loops=1)
   -> Table scan on pedidos  (cost=50673 rows=500076)
        (actual time=0.18..101 rows=500000 loops=1)

Criar um índice composto pelas duas colunas do WHERE, na ordem em que o filtro as usa, muda esse quadro. Em seguida, o mesmo comando devolve outro plano e outra ordem de grandeza:




explain-depois.sql
CREATE INDEX idx_cliente_status ON pedidos (cliente_id, status);
 
+------+--------------------+--------------------+------+----------+
| type | possible_keys      | key                | rows | filtered |
+------+--------------------+--------------------+------+----------+
| ref  | idx_cliente_status | idx_cliente_status |   25 |   100.00 |
+------+--------------------+--------------------+------+----------+
 
-> Index lookup on pedidos using idx_cliente_status
     (cliente_id=4242, status='pago')
     (cost=8.75 rows=25) (actual time=0.0329..0.0352 rows=25 loops=1)

Em números: a varredura levou 128 ms e leu 500 mil linhas. Por outro lado, o acesso por índice levou 0,035 ms e leu 25. São mais de três ordens de grandeza, na mesma máquina, com o mesmo dado e a mesma consulta.

Na tela de estrutura da tabela aparecem os índices criados, com a cardinalidade que o otimizador consulta para escolher o plano:

 
Aba Estrutura da tabela pedidos no phpMyAdmin 5.2.2, com as seis colunas e seus tipos acima do bloco Índices, que lista a chave primária e os dois índices criados no laboratório com a cardinalidade medida de cada coluna

 

A cardinalidade apontou 4.953 valores distintos em cliente_id, contra 5.000 reais na tabela. Trata-se de estimativa do InnoDB, calculada por amostragem: ela serve ao otimizador, nunca a relatório.

Índice também custa. Os dois índices da tabela ocupam 20,0 MB contra 41,6 MB de dados. Cada INSERT passa a atualizar essas árvores, portanto índice que nenhuma consulta usa é despesa sem retorno.

 

Quando o índice existe e o MySQL não usa

Criar o índice não garante que o otimizador vá aproveitá-lo. Envolver a coluna indexada numa função anula o índice, porque o banco precisaria calcular a função em cada linha antes de comparar o resultado.

As duas consultas abaixo devolvem exatamente as mesmas 556 linhas. Somente uma delas aproveita o índice de criado_em:




funcao-no-where.sql
-- ERRADO: DATE() sobre a coluna indexada forca a leitura de tudo
EXPLAIN ANALYZE SELECT COUNT(*) FROM pedidos
 WHERE DATE(criado_em) = '2026-08-15';
 
-> Filter: (cast(pedidos.criado_em as date) = '2026-08-15')
     (actual time=135..137 rows=556 loops=1)
   -> Covering index scan on pedidos using idx_criado_em
        (actual time=0.074..113 rows=500000 loops=1)
 
-- CERTO: a faixa deixa a coluna sozinha e o indice volta a valer
EXPLAIN ANALYZE SELECT COUNT(*) FROM pedidos
 WHERE criado_em >= '2026-08-15 00:00:00'
   AND criado_em <  '2026-08-16 00:00:00';
 
-> Covering index range scan on pedidos using idx_criado_em
     (cost=113 rows=556)
     (actual time=0.0146..0.0926 rows=556 loops=1)

Repare na diferença: a versão com DATE() leu 500 mil linhas em 137 ms. Já a versão com faixa leu 556 linhas em 0,161 ms. O resultado é idêntico, o custo não.

A mesma armadilha aparece com UPPER() no WHERE, com concatenação de colunas e com comparação entre tipos diferentes. Vale a regra prática: deixe a coluna indexada sozinha de um lado do operador.

 

Banco de Dados & Performance

Monitore replicação, queries lentas e conexões antes que o banco vire gargalo.

Visibilidade contínua de PostgreSQL, MySQL, Oracle e SQL Server, com alertas de bloat, locks e degradação de performance integrados à sua operação de TI.

Fale com um Especialista →

 

Conclusão

O MySQL aguenta bastante carga antes de precisar de ajuste. É por isso que o gerenciamento costuma ficar para depois: nada quebra enquanto o volume é pequeno. A conta chega junto com o crescimento.

Gerenciar não é rodar SHOW STATUS de vez em quando. É acompanhar o aproveitamento do buffer pool e ler o log de queries lentas. Além disso, é conferir a razão entre linhas lidas e devolvidas em cada consulta cara. Por fim, é verificar se a versão em produção ainda recebe correção da Oracle.

Cada um desses números tem limiar declarado. O limiar é o que separa gerenciamento de opinião. Foi exatamente isso que este artigo mediu, num laboratório com MySQL 8.4.7 e 500 mil linhas.

Num parque com dezenas de instâncias, esse acompanhamento vira rotina de governança de TI. Na prática: coleta contínua, alerta no limiar e histórico de cada mudança. Sem histórico, aliás, ninguém prova que o ajuste funcionou.

Se a sua operação precisa dessa visibilidade sobre os bancos de dados, fale com um especialista da OpServices.


 

Perguntas Frequentes

O que é o MySQL?
O MySQL é um sistema de gerenciamento de banco de dados relacional, mantido pela Oracle e disponível também em edição open source. Ele guarda os dados em tabelas com esquema definido e garante transações ACID pelo motor InnoDB. Também controla permissões por usuário e responde a consultas em SQL. Em setembro de 2026, as séries com suporte ativo são a 8.4 LTS e a 9.7 LTS.
O MySQL é um SGBD?
Sim. SGBD é a sigla de sistema de gerenciamento de banco de dados. O MySQL é um SGBD do tipo relacional. A distinção prática é esta: o banco de dados é o conjunto de dados armazenados. O SGBD é o software que grava, indexa, isola transações concorrentes e controla o acesso.
Quais são as vantagens do MySQL em comparação com um SGBD NoSQL?
O MySQL cobra esquema e integridade dentro do próprio banco. Cada coluna tem tipo, cada chave estrangeira aponta para um registro existente e a transação é ACID. Em um SGBD NoSQL essa validação sobe para a aplicação, o que dá flexibilidade de formato e transfere o risco de inconsistência. Para dado com relação forte, o modelo relacional custa menos manutenção. Para documento de formato variável e escrita massiva, o NoSQL costuma escalar melhor.
Acompanhe a OpServices10.576 profissionais de TI já seguemSeguir

Estou na OpServices desde 2011, onde sou Gerente de Marketing e Product Manager do KeepGreen, plataforma de gestão de incidentes de TI que higieniza alertas, aponta causa raiz com IA, escreve o post-mortem e analisa custos de nuvem. Também lidero os projetos de governança de inteligência artificial da empresa. Escrevo neste blog desde 2013, com mais de 550 artigos publicados sobre monitoramento, observabilidade, SRE e ITSM. LinkedIn

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *