Configure a replicação origem-réplica, o antigo master-slave, no MySQL 8.4 ou no MariaDB com GTID: my.cnf, usuário, cópia inicial e monitoramento.
Na replicação, um servidor principal, a origem (antes chamada de master), grava cada alteração em um log binário. Um ou mais servidores, as réplicas (antes slaves), leem esse log e aplicam as mesmas alterações. Serve para ter uma cópia quente pronta para assumir, separar relatórios pesados do banco principal e fazer backup sem pesar na origem.
Os nomes dos comandos mudaram. No MySQL, desde a 8.0.23 o comando é CHANGE REPLICATION SOURCE TO com START REPLICA, e a série 8.4 removeu de vez o CHANGE MASTER TO e o START SLAVE. O MariaDB continua usando CHANGE MASTER TO. Por isso o guia mostra os dois.
DROP TABLE ou um DELETE errado na origem é copiado para a réplica em segundos. Mantenha backups à parte.Cenário e pré-requisitos
- Origem:
10.0.0.11. Réplica:10.0.0.12. De preferência em rede privada. - Mesma família e versão nos dois (MySQL com MySQL, MariaDB com MariaDB). A réplica pode ser igual ou mais nova, nunca mais antiga.
- Porta 3306 da origem liberada só para a réplica. No Ubuntu com ufw:
sudo ufw allow from 10.0.0.12 to any port 3306 proto tcp
Passo 1: configure a origem
Edite o arquivo de configuração do banco (no Ubuntu e Debian, /etc/mysql/mysql.conf.d/mysqld.cnf para MySQL ou /etc/mysql/mariadb.conf.d/50-server.cnf para MariaDB; no AlmaLinux, /etc/my.cnf). Na seção [mysqld]:
MySQL 8.0, 8.4 e 9.7 (o log binário já vem ligado; falta ligar o GTID):
server_id = 11
log_bin = mysql-bin
gtid_mode = ON
enforce_gtid_consistency = ON
binlog_expire_logs_seconds = 604800
bind-address = 0.0.0.0
MariaDB (o GTID é automático, mas o log binário precisa ser ligado):
server_id = 11
log_bin = mariadb-bin
binlog_format = ROW
binlog_expire_logs_seconds = 604800
bind-address = 0.0.0.0
Reinicie: sudo systemctl restart mysql ou sudo systemctl restart mariadb. O binlog_expire_logs_seconds apaga logs com mais de 7 dias para não lotar o disco. O bind-address = 0.0.0.0 faz o banco escutar na rede; quem limita o acesso é a regra de firewall acima.
Passo 2: crie o usuário de replicação na origem
CREATE USER 'replicador'@'10.0.0.12' IDENTIFIED BY 'Troque-Esta-Senha-2026';
GRANT REPLICATION SLAVE ON *.* TO 'replicador'@'10.0.0.12';
O comando é o mesmo nos dois bancos. Use uma conta só para isso: a senha fica gravada em texto puro na réplica.
Passo 3: configure a réplica
MySQL:
server_id = 12
gtid_mode = ON
enforce_gtid_consistency = ON
MariaDB:
server_id = 12
O server_id tem de ser diferente em cada servidor. Reinicie o serviço. O modo somente leitura da réplica entra no fim, depois da importação, para não bloquear a carga dos dados.
Passo 4: copie os dados da origem para a réplica
Na origem, gere um dump consistente que já leva a posição da replicação:
MySQL:
mysqldump --all-databases --single-transaction --source-data=2 \
--routines --events --triggers | gzip > /root/inicial.sql.gz
MariaDB:
mariadb-dump --all-databases --single-transaction --master-data=2 --gtid \
--routines --events --triggers | gzip > /root/inicial.sql.gz
Copie para a réplica e importe lá:
scp /root/inicial.sql.gz [email protected]:/root/
zcat /root/inicial.sql.gz | mysql
No MySQL, o dump já ajusta o GTID da réplica sozinho. No MariaDB, pegue a posição que ficou anotada no arquivo:
zcat /root/inicial.sql.gz | grep -m1 gtid_slave_pos
A saída é algo como -- SET GLOBAL gtid_slave_pos='0-11-48213';. Guarde o valor entre aspas.
mariadb-backup (MariaDB) para a cópia inicial.Passo 5: aponte a réplica para a origem e inicie
MySQL 8.0.23 ou mais novo:
CHANGE REPLICATION SOURCE TO
SOURCE_HOST = '10.0.0.11',
SOURCE_USER = 'replicador',
SOURCE_PASSWORD = 'Troque-Esta-Senha-2026',
SOURCE_AUTO_POSITION = 1,
SOURCE_SSL = 1;
START REPLICA;
MariaDB:
SET GLOBAL gtid_slave_pos = '0-11-48213';
CHANGE MASTER TO
MASTER_HOST = '10.0.0.11',
MASTER_USER = 'replicador',
MASTER_PASSWORD = 'Troque-Esta-Senha-2026',
MASTER_USE_GTID = slave_pos;
START SLAVE;
No MariaDB 10.5 ou mais novo, START REPLICA também funciona. Em MySQL 5.7 ou anterior à 8.0.23, a sintaxe antiga é CHANGE MASTER TO ... MASTER_AUTO_POSITION = 1 com START SLAVE.
Por fim, deixe a réplica somente leitura. Isso impede que alguém grave direto nela, a causa número um de replicação quebrada; a replicação continua gravando normalmente. Rode o comando e acrescente a mesma opção no arquivo de configuração da réplica para valer após reinícios:
-- MySQL
SET GLOBAL super_read_only = ON;
-- MariaDB
SET GLOBAL read_only = ON;
Passo 6: confira se a replicação está saudável
Na réplica, rode SHOW REPLICA STATUS\G (no MariaDB, SHOW SLAVE STATUS\G) e olhe estes campos:
| MySQL | MariaDB | Esperado |
|---|---|---|
Replica_IO_Running | Slave_IO_Running | Yes |
Replica_SQL_Running | Slave_SQL_Running | Yes |
Seconds_Behind_Source | Seconds_Behind_Master | 0 ou perto de 0 |
Last_IO_Error e Last_SQL_Error | os mesmos | vazios |
Teste de verdade: crie um banco na origem (CREATE DATABASE teste_replica;), veja se ele aparece na réplica e apague-o na origem.
Problemas comuns
Authentication plugin 'caching_sha2_password' reported error: Authentication requires secure connection
No MySQL 8, o usuário de replicação usa caching_sha2_password, que exige conexão criptografada ou troca de chave. Use SOURCE_SSL = 1, como no exemplo, ou GET_SOURCE_PUBLIC_KEY = 1.
Replica_IO_Running: Connecting
A réplica não alcança a origem. Teste da réplica com mysql -h 10.0.0.11 -u replicador -p. Se não conectar, verifique o bind-address da origem, o firewall e se o usuário foi criado para o IP certo.
Source and replica have equal server ids (ou server UUIDs)
O server_id é igual nos dois, ou a réplica é um clone da máquina virtual da origem e herdou o mesmo UUID. No MySQL, pare o serviço na réplica, apague /var/lib/mysql/auto.cnf e inicie de novo: um UUID novo é gerado.
Last_SQL_Error com erro 1062 (duplicate entry) ou 1032 (can't find record)
Os dados da réplica divergiram da origem, quase sempre porque alguém gravou direto nela. Pular o erro esconde a divergência e o próximo erro vem logo. A saída segura é refazer a réplica a partir de um dump novo (passos 4 e 5, com o somente leitura desligado durante a importação) e religar o somente leitura no fim. No MySQL, antes de importar, limpe o estado antigo da réplica com STOP REPLICA; RESET REPLICA ALL; RESET BINARY LOGS AND GTIDS; (no 8.0, o último comando é RESET MASTER). Rode isso só na réplica, nunca na origem.
O disco da origem encheu de arquivos mysql-bin
Os logs binários não estão expirando. Confira o binlog_expire_logs_seconds e, com a réplica em dia, libere espaço com PURGE BINARY LOGS BEFORE NOW() - INTERVAL 3 DAY;. Nunca apague esses arquivos pelo rm.
Perguntas frequentes
Dá para fazer master-master, gravando nos dois servidores?
Dá, apontando cada servidor para o outro, mas gravações simultâneas na mesma tabela geram conflito e o problema só aparece depois. Se você precisa de vários servidores aceitando gravação, use um cluster feito para isso, como o Galera no MariaDB ou o InnoDB Cluster no MySQL.
A réplica assume sozinha se a origem cair?
Não. A replicação assíncrona não faz failover automático: você precisa promover a réplica (parar a replicação, desligar o somente leitura) e apontar os sistemas para ela. Para troca automática, veja os guias de cluster abaixo.