← Voltar ao hub MariaDB
MariaDB 04 de novembro de 2026 12 min de leitura

Replicação e failover automático no MariaDB com MaxScale: alta disponibilidade sem gambiarra

Replicação e failover automático no MariaDB com MaxScale: alta disponibilidade sem gambiarra

Quando o primário cai às 3h da manhã, quem decide o que fazer deveria ser o sistema, e não o DBA de plantão acordado pelo telefone.

Resumo para quem tem pressa: a arquitetura de alta disponibilidade mais comum com MariaDB é um primário e uma ou mais réplicas, ligadas por replicação com GTID. Na frente delas fica o MaxScale, o proxy inteligente da MariaDB, que faz três coisas: manda as escritas para o primário e as leituras para as réplicas, detecta quando o primário cai e promove uma réplica sozinho, e mantém um endpoint estável para a aplicação; a recuperação depende das conexões e dos timeouts. Somando a replicação semissíncrona, que já vem no servidor, você reduz muito o risco de perder transações na troca. Neste artigo eu monto tudo isso passo a passo.

O problema que estamos resolvendo

Sem alta disponibilidade, a queda do servidor de banco costuma seguir um roteiro triste:

  1. O monitoramento dispara e alguém acorda.
  2. Essa pessoa descobre o que aconteceu, decide qual réplica promover e executa os comandos à mão.
  3. Alguém altera o endereço do banco na configuração da aplicação e reinicia os serviços.
  4. Mais tarde, alguém precisa reconstruir o servidor antigo como réplica.

Entre o passo 1 e o 3, o sistema fica fora do ar por 30 minutos, 1 hora ou mais. Com o MaxScale, a promoção e o roteamento podem ser automáticos, e a reintegração pode ser automatizada quando não há divergências; o tempo real precisa ser medido.

As peças

Peça Papel Vem com o MariaDB?
Replicação com GTID Mantém as réplicas com cópia dos dados do primário Sim, nativa
Replicação semissíncrona Espera reconhecimento do relay log de uma réplica enquanto o modo está ativo; pode voltar ao assíncrono Sim, integrada desde o 10.3.3
Replicação paralela Faz a réplica aplicar as mudanças em várias threads, para não ficar para trás Sim, nativa
MaxScale Proxy que divide leitura e escrita, monitora e faz o failover Produto separado da MariaDB plc (veja a licença abaixo)

O GTID (Global Transaction ID) é a peça-chave. Cada transação recebe um identificador único no formato domínio-servidor-sequência, por exemplo 0-1-99812. Com isso, qualquer réplica sabe exatamente até onde já aplicou, e trocar de primário vira uma operação simples, sem precisar caçar arquivo e posição de binlog.

Passo 1: configure os servidores

No exemplo, db1 (10.0.0.11) é o primário e db2 (10.0.0.12) é a réplica. Os dois recebem quase a mesma configuração, porque qualquer um pode virar primário depois de um failover:

# /etc/mysql/mariadb.conf.d/60-replicacao.cnf
[mariadb]
server_id          = 1            # único por servidor: 1 no db1, 2 no db2
log_bin            = mariadb-bin
binlog_format      = ROW
log_slave_updates  = ON           # a réplica também grava binlog (pode virar primário)
gtid_strict_mode   = ON           # recusa transações que quebrariam a sequência de GTID

# Replicação semissíncrona (habilitada nos dois lados, em todos os servidores)
rpl_semi_sync_master_enabled = ON
rpl_semi_sync_slave_enabled  = ON
rpl_semi_sync_master_timeout = 10000   # ms; depois disso, volta a ser assíncrona

# Replicação paralela, para a réplica não ficar para trás
slave_parallel_threads = 4
slave_parallel_mode    = optimistic

Na réplica, adicione também read_only = ON, para ninguém gravar nela por engano. O MaxScale cuida de ligar e desligar isso nas trocas de papel.

Passo 2: o usuário de replicação

No primário:

CREATE USER 'repl'@'10.0.0.%' IDENTIFIED BY 'troque-esta-senha';
GRANT REPLICATION REPLICA ON *.* TO 'repl'@'10.0.0.%';

Passo 3: crie a réplica a partir de um backup

Para bases grandes, prefira o backup físico quando a compatibilidade de versões permitir; o dump continua útil quando você precisa de portabilidade. O backup físico, que copia os dados com o primário no ar e restaura rápido. Explico o mariadb-backup em detalhe no artigo sobre backup sem parar o banco. Aqui vai o resumo:

# No primário (db1): backup completo
mariadb-backup --defaults-extra-file=/etc/mysql/backup.cnf \
  --backup --target-dir=/backup/para-replica

# Copie para a réplica (db2)
rsync -a /backup/para-replica/ db2:/backup/para-replica/

# Na réplica (db2), em laboratório: preparar e restaurar
# Confirme o datadir real e preserve qualquer dado existente antes de seguir
mariadb-backup --prepare --target-dir=/backup/para-replica
systemctl stop mariadb
mv /var/lib/mysql /var/lib/mysql.antes-da-restauracao && mkdir /var/lib/mysql
mariadb-backup --copy-back --target-dir=/backup/para-replica
chown -R mysql:mysql /var/lib/mysql
systemctl start mariadb

# O GTID do momento do backup é a terceira coluna deste arquivo
cat /backup/para-replica/mariadb_backup_binlog_info
# mariadb-bin.000231    48213    0-1-99812

(Em versões anteriores ao 11.1, o arquivo se chama xtrabackup_binlog_info.)

Passo 4: ligue a réplica

Na réplica, aponte para o primário usando o GTID que o backup registrou:

SET GLOBAL gtid_slave_pos = '0-1-99812';

CHANGE MASTER TO
  MASTER_HOST     = '10.0.0.11',
  MASTER_USER     = 'repl',
  MASTER_PASSWORD = 'troque-esta-senha',
  MASTER_USE_GTID = slave_pos;

START REPLICA;
SHOW REPLICA STATUS\G

No resultado, confira três campos:

  • Slave_IO_Running: Yes e Slave_SQL_Running: Yes: a réplica está recebendo e aplicando.
  • Seconds_Behind_Master: o atraso em segundos. O ideal é ficar perto de zero.
  • Gtid_IO_Pos: até qual transação a réplica já recebeu.

Para conferir se a semissíncrona está ativa, rode no primário:

SHOW GLOBAL STATUS LIKE 'Rpl_semi_sync_master_status';   -- deve ser ON

Atenção: a semissíncrona garante que houve reconhecimento da gravação no relay log de uma réplica, não que ela já foi aplicada; a durabilidade depende também da configuração da réplica. E, se nenhuma réplica responder dentro do rpl_semi_sync_master_timeout, o primário volta a funcionar de forma assíncrona para não parar a aplicação. Monitore a variável acima: se ela ficar OFF, você perdeu essa proteção.

Passo 5: o MaxScale na frente

Primeiro, um ponto importante sobre a licença: ela depende da versão. As séries 2.0 a 24.02 usaram BSL, com autorização adicional para produção com menos de três instâncias de servidor e conversão para GPL na data definida na licença de cada versão. A partir do MaxScale 25.01, aplicam-se termos comerciais: a antiga franquia BSL de dois servidores não deve ser presumida para as versões atuais. Nosso exemplo com dois bancos não implica gratuidade: confira os termos e a assinatura do pacote escolhido nas fontes oficiais ao final. MariaDB Community Server e MaxScale são produtos com licenças distintas.

Os usuários do MaxScale

O MaxScale precisa de dois usuários: um para monitorar e executar o failover e outro para autenticar as conexões da aplicação. No primário (eles replicam para as réplicas):

-- Usuário do monitor (MariaDB 11.0.1 ou superior)
CREATE USER 'mariadbmon'@'10.0.0.%' IDENTIFIED BY 'senha-monitor';
GRANT REPLICA MONITOR, READ_ONLY ADMIN, REPLICATION SLAVE ADMIN,
      BINLOG ADMIN, CONNECTION ADMIN, PROCESS, RELOAD, SET USER,
      EVENT, SHOW DATABASES
  ON *.* TO 'mariadbmon'@'10.0.0.%';
GRANT SELECT ON mysql.user        TO 'mariadbmon'@'10.0.0.%';
GRANT SELECT ON mysql.global_priv TO 'mariadbmon'@'10.0.0.%';

-- Usuário do serviço (lê as permissões para autenticar a aplicação)
CREATE USER 'maxscale'@'10.0.0.%' IDENTIFIED BY 'senha-servico';
GRANT SHOW DATABASES ON *.* TO 'maxscale'@'10.0.0.%';
GRANT SELECT ON mysql.user          TO 'maxscale'@'10.0.0.%';
GRANT SELECT ON mysql.global_priv   TO 'maxscale'@'10.0.0.%';
GRANT SELECT ON mysql.db            TO 'maxscale'@'10.0.0.%';
GRANT SELECT ON mysql.tables_priv   TO 'maxscale'@'10.0.0.%';
GRANT SELECT ON mysql.columns_priv  TO 'maxscale'@'10.0.0.%';
GRANT SELECT ON mysql.procs_priv    TO 'maxscale'@'10.0.0.%';
GRANT SELECT ON mysql.proxies_priv  TO 'maxscale'@'10.0.0.%';
GRANT SELECT ON mysql.roles_mapping TO 'maxscale'@'10.0.0.%';

Os privilégios mudam por versão. Até o MariaDB 10.10, a documentação usa SUPER em lugar de parte da lista detalhada; no 10.11, inclua também READ_ONLY ADMIN. Preserve os privilégios de monitoramento e de leitura necessários e confira os grants oficiais da versão escolhida, em vez de copiar uma lista de outra versão. Use hosts restritos e senhas fortes; a faixa 10.0.0.% é apenas um exemplo de laboratório.

A configuração

# /etc/maxscale.cnf
[maxscale]
threads = auto

[db1]
type     = server
address  = 10.0.0.11
port     = 3306
protocol = MariaDBBackend

[db2]
type     = server
address  = 10.0.0.12
port     = 3306
protocol = MariaDBBackend

# Monitor: acompanha a topologia e faz o failover
[Monitor-Replicacao]
type                 = monitor
module               = mariadbmon
servers              = db1,db2
user                 = mariadbmon
password             = senha-monitor
replication_user     = repl
replication_password = troque-esta-senha
monitor_interval     = 2000ms
failcount            = 3          # 3 verificações falhas (~6 s) antes de agir
auto_failover        = true       # promove uma réplica se o primário cair
auto_rejoin          = true       # tenta reintegrar o antigo primário se os GTIDs permitirem
enforce_read_only_slaves = true   # aplica read_only; privilégios elevados podem contorná-lo

# Serviço: divide leitura e escrita
[Servico-RW]
type                = service
router              = readwritesplit
servers             = db1,db2
user                = maxscale
password            = senha-servico
transaction_replay  = true        # refaz no novo primário a transação interrompida
master_reconnection = true
causal_reads        = local       # a sessão lê o que acabou de escrever

# Porta onde a aplicação se conecta
[Listener-RW]
type     = listener
service  = Servico-RW
protocol = MariaDBClient
port     = 4006
systemctl enable --now maxscale
maxctrl list servers

O maxctrl list servers deve mostrar o db1 como Master, Running e o db2 como Slave, Running. A partir de agora, a aplicação deixa de se conectar ao db1 e passa a se conectar ao MaxScale, na porta 4006. Esse é o ajuste de endpoint; valide também reconexão, tratamento de erros e compatibilidade com replay de transações. O replay não cobre todo tipo de falha ou transação; não o trate como garantia de execução exatamente uma vez.

"Gravei e não li": o problema do atraso da réplica

Quem divide leitura e escrita esbarra logo nisto. O usuário salva o cadastro, a tela recarrega, a leitura vai para a réplica, que ainda não recebeu a alteração, e o cadastro "sumiu". O usuário clica em salvar de novo e duplica o registro.

O causal_reads = local acompanha o GTID das escritas da mesma conexão e espera sua aplicação na réplica antes de ler, com tratamento de timeout pelo roteador. Não garante causalidade automaticamente em outra conexão do pool: salvar um cadastro e recarregar a tela pode usar conexões diferentes. Avalie global quando as conexões passam pelo mesmo serviço, e confira os limites entre instâncias diferentes do MaxScale.

Antes do MaxScale 24.02, todos os backends precisam incluir last_gtid em session_track_system_variables. Desde o 24.02, o MaxScale configura esse acompanhamento automaticamente nas novas conexões de backend. Confirme os detalhes da versão instalada na documentação do Readwritesplit.

Testando o failover (antes de precisar dele)

Primeiro, a troca planejada, que é o que você usa para manutenção, como atualizar a versão do MariaDB:

# Promove o db2 a primário e rebaixa o db1 a réplica, de forma controlada
maxctrl call command mariadbmon switchover Monitor-Replicacao db2 db1
maxctrl list servers

Depois, o teste que interessa, que é a queda de verdade:

# No db2 (primário após o switchover): simula a queda
systemctl stop mariadb

# No host administrativo: aguarde o db1 ser promovido a Master
watch -n1 maxctrl list servers

# No db2: reinicie; se elegível ao auto_rejoin, volta como réplica de db1
systemctl start mariadb

Faça isso com a aplicação de teste rodando e gravando. Meça a indisponibilidade: ela depende da detecção, dos timeouts, do atraso da réplica e da recuperação das conexões. Teste também falhas de rede e divergências, não apenas o desligamento limpo do serviço.

Atenção: em replicação assíncrona, o failover pode perder transações que o primário confirmou mas ainda não tinha enviado a nenhuma réplica. A semissíncrona reduz muito essa janela. Nas versões que documentam esse valor, auto_failover = safe recusa a promoção quando os GTIDs observados indicam perda de dados. Isso não garante perda zero: uma escrita após a última consulta do monitor pode não ter sido observada antes da queda. Confirme o suporte na versão instalada.

E se o MaxScale cair?

O MaxScale vira o ponto de entrada da aplicação, então ele também não pode ser um ponto único de falha. A solução usual é rodar dois MaxScale atrás de um IP virtual (com keepalived, por exemplo) ou de um balanceador. Os monitores dos dois podem ser configurados para cooperar, de modo que só um deles execute o failover de cada vez (parâmetro cooperative_monitoring_locks).

Replicação + MaxScale ou Galera?

Replicação + MaxScale Galera Cluster
Escrita Em um servidor (o primário) Em qualquer nó
Replicação Assíncrona ou semissíncrona Virtualmente síncrona; aplicação e leitura ainda exigem atenção à causalidade
Latência de escrita Baixa Maior (todos os nós precisam concordar)
Distância entre servidores Tolera bem servidores longe um do outro Funciona melhor com nós próximos
Topologia prática 2 bancos no exemplo; redundância do proxy é separada Em geral 3 participantes para quorum; pode haver arbitrador
Tempo de recuperação Depende do monitor, réplica e aplicação Depende do quorum, roteamento e aplicação

Para a maioria das aplicações, replicação com MaxScale é o caminho mais simples e com melhor desempenho de escrita. O Galera faz sentido quando você precisa de replicação virtualmente síncrona e quorum, aceitando os custos de latência e operação. Nenhuma dessas escolhas dispensa testes de durabilidade e recuperação.

O que isso significa para você

  • Ative GTID e log_slave_updates em todos os servidores, mesmo que hoje você só tenha um.
  • Prefira mariadb-backup em bases grandes com versões compatíveis; use dump quando precisar de portabilidade.
  • Ligue a semissíncrona e monitore Rpl_semi_sync_master_status.
  • Ligue a replicação paralela para a réplica não ficar para trás.
  • Coloque o MaxScale na frente, com auto_failover, auto_rejoin e causal_reads.
  • Teste o failover com a aplicação rodando, antes que a vida real teste por você.

Tudo do lado do servidor (GTID, semissíncrona, replicação paralela) é nativo e gratuito no MariaDB Community. O MaxScale completa o quadro com a parte que mais tira o sono: decidir sozinho, às 3h da manhã, o que fazer quando o primário cai.


Leia também

Todos os artigos sobre MariaDB →

Documentação oficial consultada

Nota técnica: os exemplos foram revisados com a documentação, mas não executados em um servidor MariaDB nesta publicação. Valide versão, caminhos, privilégios, restrições e comportamento em laboratório antes de usar em produção. As capas são imagens fotográficas geradas por IA, não resultados de testes.

Me acompanhe no LinkedIn e no Instagram. Para fortalecer sua base em SQL, conheça meu livro Aprendendo MySQL. Conheça também a HTI Tecnologia.