kb.erickguedes.com
MySQL: Administração e Performance

MySQL em Produção

Aula 6 de 6

Monitoramento

-- Conexões ativas
SHOW FULL PROCESSLIST;
SELECT * FROM performance_schema.threads WHERE PROCESSLIST_STATE IS NOT NULL;

-- Tamanho das tabelas
SELECT 
    table_name,
    ROUND((data_length + index_length) / 1024 / 1024, 2) AS size_mb
FROM information_schema.tables
WHERE table_schema = 'meu_banco'
ORDER BY size_mb DESC;

-- Locks
SELECT * FROM performance_schema.metadata_locks;
SELECT * FROM performance_schema.data_locks;

-- Table status
SHOW TABLE STATUS LIKE 'pedidos'\G

Ferramentas de Monitoramento

# MySQLTuner — análise e recomendações
wget https://raw.githubusercontent.com/major/MySQLTuner-perl/master/mysqltuner.pl
perl mysqltuner.pl --user root --pass xxx

# Percona Monitoring and Management (PMM)
docker run -d -p 80:80 --name pmm percona/pmm-server:2

# pt-mysql-summary (Percona Toolkit)
pt-mysql-summary --user root --password xxx

Alta Disponibilidade

InnoDB Cluster (MySQL 8+)

# MySQL Shell
mysqlsh

# Criar cluster
dba.createCluster('meuCluster')
cluster.addInstance('root@node2:3306')
cluster.addInstance('root@node3:3306')

# Verificar
cluster.status()

ProxySQL — Load Balancer

# /etc/proxysql.cnf
mysql_servers =
(
    { address = "10.0.1.10", port = 3306, hostgroup = 0 },
    { address = "10.0.1.20", port = 3306, hostgroup = 0 },
    { address = "10.0.1.30", port = 3306, hostgroup = 0 }
)

mysql_query_rules =
(
    # SELECTs vão para replicas
    { rule_id = 1, match_pattern = "^SELECT", destination_hostgroup = 1 },
    # O resto vai para writer
    { rule_id = 2, match_pattern = ".*", destination_hostgroup = 0 }
)
# Admin
mysql -u admin -p -h 127.0.0.1 -P 6032
ProxySQL> SELECT * FROM stats_mysql_connection_pool;

Troubleshooting

-- Consultas bloqueadas
SELECT 
    r.trx_id AS waiting_trx_id,
    r.trx_mysql_thread_id AS waiting_thread,
    TIMESTAMPDIFF(SECOND, r.trx_started, NOW()) AS wait_age,
    b.trx_id AS blocking_trx_id
FROM performance_schema.data_lock_waits w
JOIN information_schema.innodb_trx r ON w.requesting_trx_id = r.trx_id
JOIN information_schema.innodb_trx b ON w.blocking_trx_id = b.trx_id;

-- Matar conexão
KILL CONNECTION 1234;

-- Tamanho do binlog
SHOW BINARY LOGS;
PURGE BINARY LOGS BEFORE '2024-06-01 00:00:00';

-- Erro de "too many connections"
SHOW VARIABLES LIKE 'max_connections';
SET GLOBAL max_connections = 500;
-- Solução permanente: /etc/mysql/mysql.conf.d/mysqld.cnf

Production Checklist

  • InnoDB (nunca MyISAM)
  • buffer pool 70-80% RAM
  • slow_query_log ativo
  • Backup automático configurado
  • Replicação ou cluster para HA
  • max_connections adequado
  • utf8mb4 character set
  • Monitoramento (PMM ou similar)
  • Sistema de arquivos: XFS ou ext4
  • Kernel: swappiness baixo (vm.swappiness=1)
  • IO scheduler: deadline/none (SSD)
  • ProxySQL ou HAProxy para distribuir carga
  • SSL/TLS para conexões
  • Audit log (MySQL Enterprise / Percona Audit)
  • Limite de memória por query (tmp_table_size)
  • Connection pooling (ProxySQL, HikariCP)
  • Alertas: conexões, espaço, replicação lag
  • Manutenção periódica: OPTIMIZE TABLE, ANALYZE TABLE
# Verificar integridade
mysqlcheck -u root -p --all-databases --check

# Otimizar tabelas (InnoDB: ALTER TABLE ... ENGINE=InnoDB)
mysqlcheck -u root -p --optimize meu_banco

# Atualizar estatísticas
mysqlcheck -u root -p --analyze meu_banco

Produção: InnoDB, backup, replicação + ProxySQL, monitoramento. InnoDB Cluster para HA automático. Sempre teste restores — backup que não é testado não é backup.