TL;DR — Resumo Rápido
Guia completo de replicacao MySQL master-slave para alta disponibilidade: binary logs, configuracao de slaves, monitoramento de lag, failover e ProxySQL.
A replicacao do MySQL permite que um servidor (o master) transmita cada alteracao de dados para um ou mais servidores replica (slaves) em tempo quase real. O resultado e uma arquitetura de alta disponibilidade onde o trafego de leitura e distribuido entre varios nos, backups podem ser feitos a partir de um slave sem afetar o master, e um slave pode ser promovido a master em minutos se o servidor primario falhar. Este guia cobre a configuracao completa de replicacao master-slave no MySQL 8.0: desde a configuracao de binary logs e sincronizacao inicial de dados ate monitoramento de lag, recuperacao de replicacao quebrada, procedimentos de failover e separacao de leitura/escrita com ProxySQL.
Arquitetura de Replicacao
A replicacao do MySQL funciona atraves de tres componentes trabalhando em conjunto:
- Binary log (binlog) — o master registra cada transacao confirmada em um arquivo de log sequencial. Existem tres formatos:
STATEMENT(registra o texto SQL),ROW(registra os valores antes/depois das linhas modificadas) eMIXED(usa STATEMENT por padrao e muda para ROW para funcoes nao deterministas). Sempre useROWem producao. - IO thread — uma thread no slave se conecta ao master, le os novos eventos do binary log e os escreve no relay log local.
- SQL thread — uma segunda thread no slave le o relay log e reproduz os eventos no banco de dados local, mantendo os dados sincronizados.
Modos de Replicacao
| Modo | Como Funciona | Quando Usar |
|---|---|---|
| Assincrono (padrao) | O master nao aguarda ACK do slave | HA geral, escalonamento de leituras |
| Semi-sincrono | Master aguarda ao menos um slave gravar o relay log | Dados financeiros, menor risco de perda |
| Group Replication | Multi-master com protocolo de consenso (Paxos) | Ativo-ativo, failover automatico |
Pre-requisitos
- Dois servidores Linux com MySQL 8.0 ou 8.4 (Ubuntu 22.04+ ou RHEL 9+)
- Acesso root ou sudo em ambos os servidores
- Conectividade de rede entre master e slave (porta 3306 aberta)
- server-id do master e do slave devem ser inteiros unicos em toda a topologia
Passo 1: Configurar o Servidor Master
Edite a configuracao do MySQL no master:
sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf
Adicione ou modifique essas configuracoes na secao [mysqld]:
[mysqld]
# ID unico para este servidor — deve ser diferente em cada no
server-id = 1
# Habilita o binary log — obrigatorio para replicacao
log-bin = /var/log/mysql/mysql-bin
binlog-format = ROW
# Manter 7 dias de binary logs
expire_logs_days = 7
# Sincroniza o binlog para disco a cada commit — evita perda de dados
sync_binlog = 1
# Replicacao baseada em GTID (recomendada para MySQL 8.0+)
gtid_mode = ON
enforce_gtid_consistency = ON
Aplique a configuracao:
sudo systemctl restart mysql
Verifique que o binary log esta ativo:
SHOW VARIABLES LIKE 'log_bin';
-- log_bin | ON
SHOW MASTER STATUS\G
-- File: mysql-bin.000003
-- Position: 1573
Passo 2: Criar o Usuario de Replicacao
No master, crie um usuario dedicado com apenas as permissoes necessarias para replicacao:
CREATE USER 'repl'@'192.168.1.102' IDENTIFIED BY 'ReplStr0ng!Pass';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'192.168.1.102';
FLUSH PRIVILEGES;
Substitua 192.168.1.102 pelo IP real do slave. Nunca use % (qualquer host) para usuarios de replicacao — restrinja por IP por seguranca.
Passo 3: Tirar um Snapshot Consistente
Voce precisa de um snapshot consistente em um ponto no tempo do master para inicializar o slave. O flag --master-data registra automaticamente a posicao do binary log dentro do arquivo de dump.
# Opcao A: mysqldump (adequado para bancos de dados abaixo de ~50 GB)
mysqldump -u root -p \
--all-databases \
--master-data=2 \
--single-transaction \
--flush-logs \
--routines \
--triggers \
> /tmp/master_dump.sql
# Opcao B: Percona XtraBackup (recomendado para bancos grandes, sem bloqueio de tabelas)
xtrabackup --backup --user=root --password=minhasenha \
--target-dir=/tmp/xtrabackup/
xtrabackup --prepare --target-dir=/tmp/xtrabackup/
Transfira o dump para o slave:
scp /tmp/master_dump.sql usuario@192.168.1.102:/tmp/
Passo 4: Configurar o Servidor Slave
No slave, edite mysqld.cnf:
[mysqld]
# Deve ser diferente do master e de todos os outros slaves
server-id = 2
# Localizacao do relay log
relay-log = /var/log/mysql/mysql-relay-bin
# Evita escritas acidentais no slave
read_only = 1
super_read_only = 1
# Necessario se este slave tambem sera um master (replicacao em cadeia)
log_slave_updates = 1
# Coincide com as configuracoes GTID do master
gtid_mode = ON
enforce_gtid_consistency = ON
sudo systemctl restart mysql
Passo 5: Importar o Snapshot e Iniciar a Replicacao
Restaure o dump do master no slave:
mysql -u root -p < /tmp/master_dump.sql
Configure o slave para se conectar ao master. Com modo GTID (recomendado):
CHANGE MASTER TO
MASTER_HOST = '192.168.1.101',
MASTER_USER = 'repl',
MASTER_PASSWORD = 'ReplStr0ng!Pass',
MASTER_AUTO_POSITION = 1;
Sem GTID (baseado em posicao tradicional), encontre a posicao no comentario do dump:
grep "MASTER_LOG_FILE\|MASTER_LOG_POS" /tmp/master_dump.sql | head -5
# -- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000003', MASTER_LOG_POS=1573;
CHANGE MASTER TO
MASTER_HOST = '192.168.1.101',
MASTER_USER = 'repl',
MASTER_PASSWORD = 'ReplStr0ng!Pass',
MASTER_LOG_FILE = 'mysql-bin.000003',
MASTER_LOG_POS = 1573;
Inicie a replicacao:
START SLAVE;
Passo 6: Monitorar a Saude da Replicacao
SHOW SLAVE STATUS\G
Campos chave a verificar:
Slave_IO_Running: Yes -- thread IO conectada e em execucao
Slave_SQL_Running: Yes -- thread SQL reproduzindo eventos
Seconds_Behind_Master: 0 -- slave completamente atualizado
Last_IO_Error: (vazio) -- sem erros de conexao
Last_SQL_Error: (vazio) -- sem erros de reproducao
Para monitoramento continuo via performance_schema (MySQL 8.0+):
SELECT
CHANNEL_NAME,
SERVICE_STATE,
LAST_ERROR_MESSAGE,
LAST_HEARTBEAT_TIMESTAMP
FROM performance_schema.replication_connection_status;
Tratamento do Lag de Replicacao
O lag de replicacao (Seconds_Behind_Master crescendo) e comum sob cargas de escrita intensas:
| Causa | Solucao |
|---|---|
| Thread SQL single-threaded | Habilite workers de replicacao paralela |
| Consultas lentas no slave | Identifique com SHOW PROCESSLIST; otimize |
| Gargalo de I/O no slave | Mova os relay logs para armazenamento mais rapido |
| Transacoes em massa | Divida em lotes menores no master |
| Latencia de rede | Co-localize master e slaves no mesmo datacenter |
Habilitar replicacao paralela (MySQL 8.0):
STOP SLAVE SQL_THREAD;
SET GLOBAL slave_parallel_workers = 4;
SET GLOBAL slave_parallel_type = 'LOGICAL_CLOCK';
START SLAVE SQL_THREAD;
Corrigindo Replicacao Quebrada
Quando Slave_SQL_Running: No aparece em SHOW SLAVE STATUS:
Pular uma Unica Transacao com Erro
STOP SLAVE;
SET GLOBAL sql_slave_skip_counter = 1;
START SLAVE;
SHOW SLAVE STATUS\G
Pular por GTID (Mais Seguro com Modo GTID)
STOP SLAVE;
-- Substitua pelo GTID da mensagem Last_SQL_Error
SET GTID_NEXT = 'a1b2c3d4-1111-2222-3333-444444444444:1234';
BEGIN; COMMIT;
SET GTID_NEXT = 'AUTOMATIC';
START SLAVE;
Ressincronizacao Completa a partir do Master
STOP SLAVE;
RESET SLAVE ALL;
-- Tire o snapshot novamente a partir do Passo 3 e reconfigure
Failover: Promovendo um Slave a Master
Quando o master falha e voce precisa promover um slave:
-- No slave a ser promovido:
SHOW SLAVE STATUS\G
-- Seconds_Behind_Master: 0
STOP SLAVE;
RESET SLAVE ALL;
-- Desabilita modo somente leitura — este servidor e agora o master
SET GLOBAL read_only = 0;
SET GLOBAL super_read_only = 0;
Atualize as strings de conexao da aplicacao para o novo IP do master e reconfigure os slaves restantes:
-- Nos slaves restantes:
STOP SLAVE;
CHANGE MASTER TO
MASTER_HOST = '192.168.1.102',
MASTER_AUTO_POSITION = 1;
START SLAVE;
Passo 7: ProxySQL para Separacao Leitura/Escrita
O ProxySQL fica entre a aplicacao e o MySQL, roteando escritas para o master e leituras para os slaves de forma transparente.
# Instalar ProxySQL (Ubuntu)
wget -O - 'https://repo.proxysql.com/ProxySQL/repo_pub_key' | sudo apt-key add -
echo "deb https://repo.proxysql.com/ProxySQL/proxysql-2.x/$(lsb_release -sc)/ ./" \
| sudo tee /etc/apt/sources.list.d/proxysql.list
sudo apt update && sudo apt install proxysql
sudo systemctl enable --now proxysql
Configure atraves da interface admin do ProxySQL (porta 6032):
-- Adicionar servidores: hostgroup 0 = escrita (master), hostgroup 1 = leitura (slave)
INSERT INTO mysql_servers (hostgroup_id, hostname, port) VALUES
(0, '192.168.1.101', 3306),
(1, '192.168.1.102', 3306);
-- Adicionar usuario da aplicacao
INSERT INTO mysql_users (username, password, default_hostgroup) VALUES
('appuser', 'AppPass123!', 0);
-- Rotear consultas SELECT para o hostgroup de leitura
INSERT INTO mysql_query_rules (rule_id, active, match_digest, destination_hostgroup, apply) VALUES
(1, 1, '^SELECT.*', 1, 1);
-- Aplicar e persistir mudancas
LOAD MYSQL SERVERS TO RUNTIME; SAVE MYSQL SERVERS TO DISK;
LOAD MYSQL USERS TO RUNTIME; SAVE MYSQL USERS TO DISK;
LOAD MYSQL QUERY RULES TO RUNTIME; SAVE MYSQL QUERY RULES TO DISK;
A aplicacao se conecta ao ProxySQL na porta 6033 e todo o roteamento e gerenciado de forma transparente.
Comparacao: Replicacao MySQL vs Alternativas
| Solucao | Arquitetura | Failover | Escalonamento de Escrita | Complexidade |
|---|---|---|---|---|
| Replicacao MySQL | Master + slaves | Manual ou MHA | Nao (master unico) | Baixa |
| MySQL Group Replication | Multi-master Paxos | Automatico | Limitado | Media |
| Galera Cluster (MariaDB) | Multi-master sincrono | Automatico | Sim | Media |
| Vitess | MySQL com sharding | Automatico | Sim (sharding) | Alta |
| PlanetScale | Vitess gerenciado | Gerenciado | Sim | Baixa (gerenciado) |
| PostgreSQL Streaming | Primario + standbys | Patroni/manual | Nao | Baixa-Media |
Pontos de Atencao
- server-id deve ser globalmente unico em todos os nos — dois nos com o mesmo ID corrompem silenciosamente a replicacao
read_only=1nao bloqueia usuarios SUPER — usesuper_read_only=1para bloquear completamente o slave- Transacoes grandes bloqueiam a thread IO — use
pt-online-schema-changepara operacoes DDL grandes - Diferenca de fuso horario causa erros de replicacao — defina
default-time-zone='+00:00'em todos os nos
Resumo
- A replicacao MySQL usa binary logs, threads IO e threads SQL para manter os slaves sincronizados
- Use
binlog-format=ROW,sync_binlog=1e modo GTID (gtid_mode=ON) em producao - Monitore
Slave_IO_Running,Slave_SQL_RunningeSeconds_Behind_Mastercontinuamente - Habilite workers de replicacao paralela para reduzir o lag sob cargas de escrita intensas
- Use
RESET SLAVE ALLpara uma reconfiguracao limpa em vez de tentar corrigir um estado quebrado - O ProxySQL roteia transparentemente leituras para os slaves e escritas para o master