MySQL Replication com GTID na prática: simulando failover e recuperação do ambiente

Em ambientes críticos, indisponibilidade de banco de dados não é uma opção.

Por isso, uma arquitetura com replicação e failover é essencial para garantir continuidade do serviço.

Neste post vamos fazer um laboratório completo:

  • configurar replicação com GTID
  • criar um master e uma réplica
  • simular queda do master
  • promover automaticamente a réplica
  • inserir novos dados
  • trazer o antigo master de volta como réplica
  • validar que tudo sincronizou corretamente

Tudo isso com comandos reais e validações práticas.

Arquitetura do laboratório

Ambiente utilizado:

Master original

mysql01
IP: 10.0.0.73
server-id: 1

Replica

mysql02
IP: 10.0.0.147
server-id: 2

Configuração inicial do GTID

Em ambos os servidores configuramos no my.cnf.

server-id=1 (ou 2 na replica)
log_bin=binlog
binlog_format=ROW
gtid_mode=ON
enforce_gtid_consistency=ON
log_slave_updates=ON

Reiniciamos o MySQL:

systemctl restart mysqld

Validação:

SELECT
@@hostname,
@@server_id,
@@gtid_mode,
@@enforce_gtid_consistency,
@@log_bin,
@@binlog_format,
@@log_slave_updates;

Resultado esperado:
*************************** 1. row ***************************
                @@hostname: mysql02.localdomain
               @@server_id: 2
               @@gtid_mode: ON
@@enforce_gtid_consistency: ON
                 @@log_bin: 1
           @@binlog_format: ROW
       @@log_slave_updates: 1

–Master
Criando usuário de replicação

No mysql01 (master):

CREATE USER 'repl'@'%' IDENTIFIED WITH mysql_native_password BY 'Senha123';

GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';

FLUSH PRIVILEGES;

Criando banco de teste

CREATE DATABASE lab_failover;

USE lab_failover;

CREATE TABLE pedidos (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
cliente VARCHAR(100),
valor DECIMAL(10,2),
data_criacao TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

Inserindo dados iniciais:

INSERT INTO pedidos (cliente, valor)
VALUES
('CLIENTE_1',100),
('CLIENTE_2',200),
('CLIENTE_3',300);
Configurando a réplica com GTID

Na Replica

Configurar a replicação

CHANGE REPLICATION SOURCE TO
SOURCE_HOST='10.0.0.73',
SOURCE_USER='repl',
SOURCE_PASSWORD='Senha123',
SOURCE_AUTO_POSITION=1;

START REPLICA;

Para validar a replicação execute o comando abaixo.


SHOW REPLICA STATUS\G

Campos importantes:

Replica_IO_Running: Yes
Replica_SQL_Running: Yes
Seconds_Behind_Source: 0
Auto_Position: 1

Criando script de monitoramento e promoção automática

Criamos um script simples que verifica se o master está disponível, caso não esteja, promove a réplica automaticamente.

mysql_failover.sh

Conteúdo:

#!/bin/bash

MASTER="10.0.0.73"
REPLICA="127.0.0.1"
MYSQL_USER="monitor"
MYSQL_PASS="Senha123"
LOG="/var/log/mysql_failover.log"

DATA=$(date "+%Y-%m-%d %H:%M:%S")

mysql -h $MASTER -u $MYSQL_USER -p$MYSQL_PASS -e "SELECT 1;" >/dev/null 2>&1

if [ $? -ne 0 ]; then

echo "$DATA - Master $MASTER indisponível. Iniciando promoção da réplica." >> $LOG

mysql -h $REPLICA -u $MYSQL_USER -p$MYSQL_PASS -e "
STOP REPLICA;
RESET REPLICA ALL;
SET GLOBAL read_only = OFF;
"

echo "$DATA - Réplica promovida a MASTER com sucesso." >> $LOG

else

echo "$DATA - Master OK." >> $LOG

fi

No master crie o usuario que utilizara o script.

CREATE USER 'monitor'@'%' IDENTIFIED BY 'Senha123';

GRANT SYSTEM_VARIABLES_ADMIN ON *.* TO 'monitor'@'%';
GRANT REPLICATION_SLAVE_ADMIN ON *.* TO 'monitor'@'%';
GRANT REPLICATION CLIENT ON *.* TO 'monitor'@'%';
GRANT RELOAD ON *.* TO 'monitor'@'%';

FLUSH PRIVILEGES;

Agendando execução automática

Adicionamos no cron:

crontab -e
* * * * * /home/mysql_failover.sh

O script roda a cada 1 minuto.

Simulando queda do master

systemctl stop mysqld

O log registrou:

2026-03-14 12:34:01 - Master 10.0.0.73 indisponível. Iniciando promoção da réplica.
2026-03-14 12:34:01 - Réplica promovida a MASTER com sucesso.

Validando promoção da réplica

No mysql02:

SHOW REPLICA STATUS;

Resultado:

Empty set

Isso indica que ele não está mais replicando.

Confirmando escrita liberada:

SELECT @@read_only;

Resultado:

0

Verificando binlog ativo:

SHOW MASTER STATUS;
*************************** 1. row ***************************
             File: binlog.000004
         Position: 5185
     Binlog_Do_DB:
 Binlog_Ignore_DB:
Executed_Gtid_Set: 00c7b540-1fa7-11f1-ab7f-080027897cb8:1-18,
b5e7f644-1fad-11f1-a884-0800273938b6:1-2
1 row in set (0,00 sec)

Agora o mysql02 é o novo master.

Inserindo novos dados após o failover

No novo master:

USE lab_failover;

INSERT INTO pedidos (cliente, valor)
VALUES
('DEPOIS_FAILOVER_1',500),
('DEPOIS_FAILOVER_2',750);

Subindo novamente o antigo master

No mysql01:


systemctl start mysqld

Configurando replicação para o novo master:

CHANGE REPLICATION SOURCE TO
SOURCE_HOST='10.0.0.147',
SOURCE_USER='repl',
SOURCE_PASSWORD='Senha123',
SOURCE_AUTO_POSITION=1;

Iniciar replicação:

START REPLICA;

Validando sincronização

No mysql01:

SHOW REPLICA STATUS\G

Resultado esperado:

Replica_IO_Running: Yes
Replica_SQL_Running: Yes
Seconds_Behind_Source: 0
Source_Host: 10.0.0.147

Validando dados replicados

No mysql01:

USE lab_failover;
SELECT * FROM pedidos ORDER BY id;

Os registros inseridos após o failover também aparecerão:

+----+-------------------+--------+---------------------+
| id | cliente           | valor  | data_pedido         |
+----+-------------------+--------+---------------------+
|  1 | Joao              | 100.00 | 2026-03-14 11:41:23 |
|  2 | Maria             | 200.00 | 2026-03-14 11:41:23 |
|  3 | Carlos            | 150.00 | 2026-03-14 11:41:23 |
|  4 | Ana               | 350.00 | 2026-03-14 12:03:29 |
|  5 | ANTES_DA_QUEDA    | 999.00 | 2026-03-14 12:05:58 |
|  6 | DEPOIS_FAILOVER_1 | 500.00 | 2026-03-14 12:39:03 |
|  7 | DEPOIS_FAILOVER_2 | 750.00 | 2026-03-14 12:39:03 |
+----+-------------------+--------+---------------------+

Teste final de sincronismo

No master atual:

INSERT INTO pedidos (cliente, valor)
VALUES ('ULTIMO_TESTE_GTID',999);

Na réplica:

SELECT * FROM pedidos
WHERE cliente='ULTIMO_TESTE_GTID'\G;

*************************** 1. row ***************************
         id: 8
    cliente: ULTIMO_TESTE_GTID
      valor: 999.00
data_pedido: 2026-03-14 13:16:32
1 row in set (0,00 sec)

Registro replicado com sucesso.

Considerações finais

Neste laboratório vimos na prática como o GTID simplifica bastante a administração de replicação no MySQL.

Diferente do modelo tradicional baseado em file e position, o GTID permite que a réplica saiba exatamente quais transações já foram executadas, eliminando boa parte da complexidade na hora de reconstruir ou reposicionar uma replicação.

Isso torna operações como:

  • recriar réplicas
  • promover um novo master
  • reintegrar servidores.

muito mais simples e seguras.

No laboratório simulamos um cenário real:

  • o master ficou indisponível
  • a réplica foi promovida automaticamente
  • novos dados foram gravados no novo master
  • o antigo master voltou ao ambiente se tornando uma replica e passou a sincronizar transações.

Tudo isso sem precisar lidar manualmente com posições de binlog, justamente graças ao uso de GTID com AUTO_POSITION.

Claro que em um ambiente de produção existem outros componentes importantes que normalmente fazem parte da arquitetura.

Um exemplo clássico é o uso de um VIP (Virtual IP) ou algum mecanismo de balanceamento que redirecione automaticamente as conexões da aplicação para o novo master após um failover.

Dessa forma, quando ocorre a promoção de uma réplica, as aplicações continuam funcionando sem precisar alterar manualmente o endpoint de conexão.

Existem diversas ferramentas que ajudam a automatizar esse tipo de cenário, como:

  • MySQL Orchestrator
  • ProxySQL
  • HAProxy
  • Keepalived para gerenciamento de VIP

Mas mesmo em arquiteturas mais simples, entender como o GTID funciona e como a promoção de uma réplica ocorre já é um grande passo para construir ambientes mais resilientes ja que em caso de falha do servidor principal, a réplica pode assumir rapidamente, evitando uma indisponibilidade total do banco de dados.

Importante.
Antes de habilitar o GTID em produção, também é importante validar se as aplicações estão aptas a operar com esse modelo de transação. Para isso, uma boa prática é habilitar inicialmente o parâmetro enforce_gtid_consistency em modo WARN, permitindo identificar nos logs possíveis operações incompatíveis. Dessa forma é possível ajustar o ambiente com segurança antes de ativar o GTID definitivamente.

E o mais importante: testar esses cenários em laboratório antes de precisar deles em produção.


Deixe uma resposta