DBA BRABOMentoria Técnica para DBAs

Mentoria Técnica Avançada

MySQL

Administração • Replicação • Alta Disponibilidade • Backup • Performance • Segurança

Entenda como o MySQL processa transações, persiste dados no InnoDB, registra operações no Binary Log e mantém réplicas consistentes em diferentes arquiteturas.

Intermediário → Avançado 6 módulos 46 tópicos Sob consulta
Banner da mentoria MySQL — DBA BRABO

O que essa mentoria cobre

Pilares

Os eixos de trabalho desta formação — cada um vira teoria, lab e troubleshooting.

Administração

Implementação, gerenciamento geral

Replicação

GTID, Semi-sync e Group Replication sem downtime

Alta Disponibilidade

InnoDB Cluster, MySQL Router e failover automático

Backup & Restore

XtraBackup, PITR e validação de restore

Performance & Tuning

Performance Schema, Optimizer e queries lentas

Segurança

TDE, audit plugin, roles e criptografia em trânsito (TLS)

Conteúdo programático

Módulos e tópicos

Clique para abrir. Os módulos marcados como detalhado trazem, por tópico, conceito, funcionamento, o que é implementado no lab, troubleshooting e comandos.

Conceito

Replicação assíncrona em que a instância primária (source) registra toda alteração de dados no Binary Log e uma ou mais réplicas leem esse log e reaplicam as mesmas alterações localmente. A réplica identifica seu ponto de leitura por um par arquivo + posição — por exemplo mysql-bin.000042 e o offset 19483. O source não espera confirmação da réplica para dar COMMIT: por isso é assíncrona, e por isso existe a possibilidade real de perda de dados em um failover.

Como funciona

  • A sessão executa a transação e faz COMMIT. Antes de responder ao cliente, o MySQL grava o evento no Binary Log da própria instância primária.
  • Na réplica, a thread de I/O abre uma conexão de replicação com o source, pede os eventos a partir do arquivo e posição que ela guarda, e grava o que recebe no Relay Log local.
  • A thread de aplicação (SQL thread, ou as worker threads quando há replicação paralela) lê o Relay Log e reexecuta os eventos no dado local.
  • A réplica persiste seu progresso — arquivo e posição já aplicados — para conseguir retomar do ponto certo após um restart.
  • O formato do binlog define o que é gravado: ROW registra a imagem das linhas alteradas, STATEMENT registra o SQL, MIXED alterna conforme a operação. ROW é o padrão e o único formato seguro para replicação com funções não determinísticas.

Na prática

  • Habilitar log_bin, definir server_id único em cada instância e escolher binlog_format=ROW.
  • Criar o usuário de replicação com o privilégio REPLICATION SLAVE e conexão restrita.
  • Provisionar a réplica a partir de um backup consistente, anotando o arquivo e a posição correspondentes ao momento do backup.
  • Apontar a réplica com CHANGE REPLICATION SOURCE TO e iniciar com START REPLICA.
  • Validar o estado com SHOW REPLICA STATUS e acompanhar Seconds_Behind_Source.
  • Configurar retenção do binlog (binlog_expire_logs_seconds) com folga suficiente para o tempo de provisionamento de uma réplica nova.

Troubleshooting

SintomaA réplica para com erro de chave duplicada ou linha não encontrada.
CausaDivergência de dados entre source e réplica — normalmente escrita direta na réplica, ou provisionamento a partir de um backup inconsistente.
AçãoDiagnosticar a divergência de verdade (comparar as linhas envolvidas) antes de qualquer coisa. Pular o evento esconde o sintoma e aprofunda a divergência; na maioria dos casos a resposta correta é reconstruir a réplica.
SintomaSeconds_Behind_Source cresce continuamente.
CausaA aplicação na réplica não acompanha o volume do source — comumente por aplicação de eventos em thread única, por falta de índice em tabela alterada, ou por I/O saturado na réplica.
AçãoVerificar se a replicação paralela está ativa e dimensionada, conferir se as tabelas replicadas têm chave primária, e medir o I/O da réplica antes de culpar a rede.
SintomaRéplica não conecta após restart do source.
CausaO binlog em que a réplica estava posicionada foi purgado, ou o arquivo e posição guardados não existem mais.
AçãoConfirmar a retenção configurada. Se o ponto foi perdido, a réplica precisa ser reconstruída — e a retenção, revista.
SintomaRéplica retorna dado diferente do source em SELECTs, sem erro nenhum.
CausaDivergência silenciosa, típica de binlog_format=STATEMENT com funções não determinísticas.
AçãoMigrar para ROW e comparar os dados com uma ferramenta de checksum de tabela.

Comandos

Configuração mínima no source ini
[mysqld]
server_id        = 1
log_bin          = /var/lib/mysql/mysql-bin
binlog_format    = ROW
binlog_expire_logs_seconds = 604800
Usuário de replicação sql
CREATE USER 'repl'@'10.0.%' IDENTIFIED BY '<senha>' REQUIRE SSL;
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'10.0.%';
Apontar e iniciar a réplica sql
CHANGE REPLICATION SOURCE TO
  SOURCE_HOST     = 'db01',
  SOURCE_USER     = 'repl',
  SOURCE_PASSWORD = '<senha>',
  SOURCE_LOG_FILE = 'mysql-bin.000042',
  SOURCE_LOG_POS  = 19483,
  SOURCE_SSL      = 1;

START REPLICA;
Verificar o estado da replicação sql
SHOW REPLICA STATUS\G
-- olhar: Replica_IO_Running, Replica_SQL_Running,
--        Seconds_Behind_Source, Last_Error

Tecnologias

MySQLBinary LogRelay LogROW formatReplicação paralela

Conceito

GTID (Global Transaction Identifier) atribui a cada transação um identificador único e permanente no formato <UUID do servidor de origem>:<número sequencial>. Cada instância mantém o conjunto de GTIDs que já executou (gtid_executed). Como o identificador é global, uma réplica consegue dizer com precisão quais transações já aplicou e pedir exatamente o que falta — sem que ninguém precise calcular arquivo e offset.

Como funciona

  • Ao dar COMMIT, o source gera o GTID da transação e o grava junto do evento no binlog.
  • A réplica registra em gtid_executed tudo o que aplicou. Esse conjunto é persistido na tabela mysql.gtid_executed, sobrevivendo a restart.
  • Com SOURCE_AUTO_POSITION=1, a réplica informa seu gtid_executed ao conectar e o source envia apenas as transações ausentes. Não existe mais arquivo e posição na configuração.
  • Em um failover, apontar as demais réplicas para o novo primário é a mesma operação de sempre: elas negociam pelo GTID. É isso que torna o failover automatizável.
  • GTIDs vazios (transações que não alteram dado) e a diretiva de transação vazia importam ao reconciliar réplicas — injetar uma transação vazia é o mecanismo suportado para marcar um GTID como aplicado quando você tem certeza de que o efeito já existe no destino.

Na prática

  • Ativar gtid_mode=ON e enforce_gtid_consistency=ON em todas as instâncias — a mudança tem ordem definida quando feita online e não pode ser aplicada de qualquer jeito.
  • Reconfigurar as réplicas com SOURCE_AUTO_POSITION=1.
  • Provisionar réplica nova a partir de backup que preserve o gtid_purged correspondente.
  • Ensaiar um failover: promover uma réplica e reapontar as demais, medindo o tempo total.
  • Monitorar a diferença entre o gtid_executed do source e o das réplicas — é a medida honesta de atraso, mais confiável que Seconds_Behind_Source.

Troubleshooting

SintomaERROR 1236 informando que o source não tem os GTIDs necessários.
CausaAs transações que a réplica precisa já foram purgadas do binlog do source.
AçãoComparar gtid_executed da réplica com gtid_purged do source. Se o intervalo faltante foi purgado, a réplica precisa ser reconstruída a partir de um backup mais recente.
SintomaRéplica não inicia acusando inconsistência de GTID.
CausaOperação não suportada sob enforce_gtid_consistency — como CREATE TABLE ... SELECT em versões que não permitem, ou tabela temporária dentro de transação.
AçãoIdentificar a operação na aplicação e substituí-la; a restrição existe porque essas construções não são representáveis atomicamente como um GTID.
SintomaApós promover uma réplica, as demais divergem.
CausaA réplica promovida não tinha aplicado tudo o que outra réplica já tinha — promoveu-se o nó errado.
AçãoAntes de promover, comparar gtid_executed de todos os candidatos e escolher o mais avançado. Automatizar essa comparação é justamente o que ferramentas de orquestração fazem.
SintomaConjunto de GTIDs cresce com UUIDs desconhecidos.
CausaAlguém escreveu diretamente em uma réplica, gerando GTIDs de origem local.
AçãoColocar as réplicas em super_read_only, não apenas read_only — read_only sozinho não impede usuário com SUPER.

Comandos

Habilitar GTID ini
[mysqld]
gtid_mode                 = ON
enforce_gtid_consistency  = ON
log_replica_updates       = ON
super_read_only           = ON   # nas réplicas
Réplica com auto-position sql
CHANGE REPLICATION SOURCE TO
  SOURCE_HOST          = 'db01',
  SOURCE_USER          = 'repl',
  SOURCE_PASSWORD      = '<senha>',
  SOURCE_AUTO_POSITION = 1;

START REPLICA;
Medir o atraso pelo conjunto de GTIDs sql
-- no source
SELECT @@GLOBAL.gtid_executed;

-- na réplica: o que ainda falta aplicar
SELECT GTID_SUBTRACT('<gtid_executed do source>',
                     @@GLOBAL.gtid_executed) AS faltando;
Escolher o candidato mais avançado antes de promover sql
-- executar em cada réplica candidata e comparar
SELECT @@GLOBAL.gtid_executed;
-- promove-se a que contém o superconjunto das demais

Tecnologias

MySQLGTIDauto-positiongtid_executedgtid_purgedsuper_read_only

Conceito

Na replicação assíncrona o source confirma o COMMIT ao cliente sem saber se alguma réplica recebeu a transação — se o source morrer nesse instante, a transação existe só nele. O semi-síncrono muda o contrato: antes de responder ao cliente, o source espera que pelo menos N réplicas confirmem ter gravado o evento no seu relay log. Confirmar recebimento não é o mesmo que ter aplicado: a réplica ainda pode estar atrás na aplicação, mas o dado não se perde com a morte do source.

Como funciona

  • O plugin semissíncrono é carregado no source e nas réplicas; cada lado tem o seu.
  • Ao dar COMMIT, o source grava no binlog e bloqueia a resposta ao cliente aguardando o ACK de rpl_semi_sync_source_wait_for_replica_count réplicas.
  • O ponto de espera importa: com AFTER_SYNC o source espera antes de tornar a transação visível, o que evita transações fantasma; com AFTER_COMMIT a transação já está visível localmente antes do ACK.
  • Se nenhum ACK chegar dentro de rpl_semi_sync_source_timeout, o source degrada automaticamente para assíncrono e segue operando — a disponibilidade é preservada em detrimento da garantia.
  • Quando uma réplica volta a acompanhar, o source retoma o modo semi-síncrono sozinho.

Na prática

  • Instalar e habilitar os plugins nos dois lados e definir o número de ACKs exigidos.
  • Dimensionar o timeout conscientemente: um valor baixo transforma o semi-síncrono em decoração; um valor alto propaga latência de rede para a aplicação.
  • Medir o impacto real no tempo de COMMIT antes e depois — a conta é sempre latência de rede somada por transação.
  • Monitorar Rpl_semi_sync_source_status para saber quando o cluster degradou para assíncrono, porque essa degradação é silenciosa para a aplicação.
  • Manter pelo menos duas réplicas semi-síncronas se a garantia precisa sobreviver à manutenção de uma delas.

Troubleshooting

SintomaLatência de escrita subiu de forma perceptível após habilitar.
CausaCada COMMIT agora paga um round-trip até a réplica.
AçãoAproximar a réplica em topologia de rede, ou reavaliar se a garantia vale o custo para essa carga. Colocar a réplica semi-síncrona em outra região é a decisão que mais surpreende negativamente.
SintomaO cluster está assíncrono sem ninguém saber.
CausaO timeout foi atingido e o source degradou automaticamente.
AçãoAlertar sobre Rpl_semi_sync_source_status = OFF. Sem esse alerta você acha que tem uma garantia que não tem.
SintomaApós failover apareceram transações no antigo primário que não existem no novo.
CausaUso de AFTER_COMMIT — a transação ficou visível localmente antes de ser confirmada remotamente.
AçãoUsar AFTER_SYNC, que é o padrão nas versões atuais justamente por causa desse cenário.

Comandos

Habilitar no source e na réplica sql
-- source
INSTALL PLUGIN rpl_semi_sync_source SONAME 'semisync_source.so';
SET GLOBAL rpl_semi_sync_source_enabled = 1;
SET GLOBAL rpl_semi_sync_source_timeout = 1000;   -- ms
SET GLOBAL rpl_semi_sync_source_wait_point = 'AFTER_SYNC';

-- réplica
INSTALL PLUGIN rpl_semi_sync_replica SONAME 'semisync_replica.so';
SET GLOBAL rpl_semi_sync_replica_enabled = 1;
STOP REPLICA IO_THREAD; START REPLICA IO_THREAD;
Confirmar que a garantia está ativa sql
SHOW STATUS LIKE 'Rpl_semi_sync_source_status';     -- ON = garantido
SHOW STATUS LIKE 'Rpl_semi_sync_source_no_tx';      -- COMMITs sem ACK
SHOW STATUS LIKE 'Rpl_semi_sync_source_avg_net_wait_time';

Tecnologias

MySQLSemi-syncAFTER_SYNCrpl_semi_syncRpl_semi_sync_source_status

Conceito

Group Replication é um plugin que transforma um conjunto de instâncias MySQL em um grupo que decide por consenso, usando uma implementação de Paxos. Cada transação, ao chegar no COMMIT, é enviada ao grupo e passa por certificação: o grupo verifica se ela conflita com outra transação concorrente já certificada. O grupo mantém membership dinâmico e só aceita escrita enquanto houver maioria — é isso que impede split-brain, ao custo de exigir quorum.

Como funciona

  • Todos os membros compartilham a mesma visão de membership. Entradas e saídas geram uma mudança de visão acordada por todos.
  • No COMMIT, o writeset da transação é difundido ao grupo em ordem total. Cada membro executa a mesma certificação e chega, deterministicamente, à mesma decisão de aceitar ou abortar.
  • Aceita a transação, cada membro aplica localmente — de forma assíncrona em relação ao COMMIT do originador, o que significa que ler de um secundário logo após escrever pode não enxergar a escrita, a menos que se use um nível de consistência mais forte.
  • O grupo só permite escrita com maioria de membros vivos. Perdida a maioria, os remanescentes ficam bloqueados por decisão de projeto — preferir indisponibilidade a divergência.
  • Em modo single-primary o grupo elege automaticamente um novo primário quando o atual sai. Em multi-primary todos aceitam escrita, e conflitos entre nós passam a ser rotina a ser tratada pela aplicação.

Na prática

  • Exigências não negociáveis: engine InnoDB, chave primária em toda tabela, binlog em ROW e GTID habilitado.
  • Dimensionar o grupo com número ímpar de membros — 3 ou 5 — porque quorum é maioria.
  • Configurar group_replication_group_seeds e a whitelist de IPs corretamente; a maior parte das falhas de bootstrap está aí.
  • Escolher conscientemente entre single-primary e multi-primary. Multi-primary não é um upgrade: é outro modelo de conflito.
  • Definir o nível de consistência de leitura conforme a aplicação, ciente de que consistência mais forte custa latência.
  • Testar a perda de quorum de propósito e documentar o procedimento de reconfiguração forçada antes de precisar dele às três da manhã.

Troubleshooting

SintomaMembro entra em ERROR e é expulso do grupo.
CausaDivergência local, transação aplicada fora do grupo, ou perda de conectividade prolongada.
AçãoLer o motivo no log de erro antes de tentar reingressar. Se o membro divergiu, o caminho é reprovisionar — o clone plugin resolve isso sem intervenção manual.
SintomaGrupo travado, sem aceitar escrita, com membros vivos.
CausaPerda de quorum — sobraram menos que a maioria.
AçãoConfirmar quantos membros o grupo espera versus quantos respondem. A reconfiguração forçada de membership resolve, mas é uma operação perigosa: aplicada no conjunto errado, cria dois grupos divergentes.
SintomaTransações abortando com erro de certificação.
CausaConflito de writeset em modo multi-primary — dois nós alterando a mesma linha concorrentemente.
AçãoRotear a escrita de cada conjunto de dados sempre para o mesmo nó, ou migrar para single-primary. Certificação não é bug, é o mecanismo funcionando.
SintomaRéplica secundária retorna dado antigo logo após uma escrita.
CausaAplicação assíncrona no secundário somada a nível de consistência EVENTUAL.
AçãoAjustar group_replication_consistency para o nível adequado, medindo o impacto de latência que isso introduz.
SintomaMembro nunca conclui o ingresso, ficando em RECOVERING.
CausaRecuperação distribuída não consegue alcançar o estado do grupo — normalmente binlog purgado no doador.
AçãoUsar o clone plugin para provisionamento físico em vez de recuperação por binlog.

Comandos

Configuração base de um membro ini
[mysqld]
server_id                         = 1
gtid_mode                         = ON
enforce_gtid_consistency          = ON
binlog_format                     = ROW
plugin_load_add                   = group_replication.so

group_replication_group_name      = 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee'
group_replication_local_address   = 'db01:33061'
group_replication_group_seeds     = 'db01:33061,db02:33061,db03:33061'
group_replication_single_primary_mode = ON
Bootstrap do grupo — só no primeiro membro, uma única vez sql
SET GLOBAL group_replication_bootstrap_group = ON;
START GROUP_REPLICATION;
SET GLOBAL group_replication_bootstrap_group = OFF;
-- deixar o bootstrap ligado em mais de um nó é como se cria dois grupos
Inspecionar membership e quem é o primário sql
SELECT MEMBER_HOST, MEMBER_PORT, MEMBER_STATE, MEMBER_ROLE
  FROM performance_schema.replication_group_members;

SELECT * FROM performance_schema.replication_group_member_stats\G

Tecnologias

MySQLGroup ReplicationPaxosQuorumCertificação de conflitoClone Pluginsingle-primarymulti-primary

Conceito

InnoDB Cluster não é um motor de replicação novo. É a composição de três peças: Group Replication fornecendo o consenso e o failover, MySQL Router fazendo o roteamento transparente das conexões, e MySQL Shell com a AdminAPI orquestrando provisionamento e operação. O ganho é operacional — provisionar, adicionar nó, promover e diagnosticar viram comandos de uma linha em vez de sequências manuais.

Como funciona

  • A AdminAPI do MySQL Shell valida os pré-requisitos de cada instância e corrige configuração automaticamente antes de formar o cluster.
  • Formado o cluster, os metadados ficam em um schema dedicado, replicado entre os membros — é ele que o Router lê para saber a topologia.
  • O MySQL Router mantém uma cópia dessa topologia e expõe duas portas: uma de leitura e escrita, que sempre aponta para o primário atual, e uma somente de leitura, que balanceia entre os secundários.
  • Quando o primário cai, o Group Replication elege o substituto e o Router redireciona as conexões novas sem que a aplicação mude configuração — não é failover transparente para conexões abertas, que ainda recebem erro e precisam reconectar.
  • Adicionar uma instância nova usa o clone plugin: o provisionamento é uma cópia física, não uma reprodução de binlog.

Na prática

  • Rodar dba.checkInstanceConfiguration() em cada nó e deixar a AdminAPI ajustar o que estiver fora do padrão.
  • Criar o cluster no primeiro nó e adicionar os demais com addInstance(), escolhendo clone como método de recuperação.
  • Instalar o Router em bootstrap contra o cluster — nunca configurá-lo à mão, porque o bootstrap gera a configuração e as credenciais corretas.
  • Decidir onde o Router roda: junto da aplicação reduz um salto de rede e elimina um ponto único de falha centralizado.
  • Ensaiar o failover com cluster.status() aberto, cronometrando quanto tempo a aplicação leva para voltar a escrever.
  • Tratar o reingresso de um nó que ficou fora por muito tempo como reprovisionamento, não como reconexão.

Troubleshooting

SintomaaddInstance falha na validação de configuração.
CausaInstância sem GTID, sem chave primária em alguma tabela, ou com server_id repetido.
AçãoLer o relatório do checkInstanceConfiguration por inteiro — ele nomeia exatamente o que falta. Tabela sem chave primária é a causa mais comum e exige mudança de schema.
SintomaAplicação recebe erro de somente leitura de forma intermitente.
CausaA conexão está indo para a porta de leitura do Router, ou foi aberta antes de um failover e continua apontando para um nó que virou secundário.
AçãoConferir a porta usada e garantir que o pool de conexões da aplicação reconecta em erro de escrita em vez de reutilizar a conexão morta.
Sintomacluster.status() reporta o cluster sem tolerância a falha.
CausaNúmero de membros ativos insuficiente para perder mais um sem perder quorum.
AçãoRestabelecer os membros ausentes. Um cluster de três nós com um fora não tolera mais nenhuma falha — o alerta precisa disparar aqui, não depois.
SintomaRouter não enxerga a mudança de primário.
CausaMetadados desatualizados ou Router sem conectividade com os membros.
AçãoVerificar a conectividade e o intervalo de atualização de metadados; um bootstrap novo do Router resolve o caso de configuração obsoleta.

Comandos

Criar o cluster js
// mysqlsh --js
dba.checkInstanceConfiguration('admin@db01:3306');
dba.configureInstance('admin@db01:3306');

var cluster = dba.createCluster('dbabrabo');
cluster.addInstance('admin@db02:3306', {recoveryMethod: 'clone'});
cluster.addInstance('admin@db03:3306', {recoveryMethod: 'clone'});
cluster.status();
Bootstrap do Router bash
mysqlrouter --bootstrap admin@db01:3306 \
            --directory /opt/router \
            --conf-use-sockets
# gera as portas de leitura/escrita e somente leitura já apontadas ao cluster
Operação do dia a dia js
cluster.status({extended:1});
cluster.setPrimaryInstance('db02:3306');   // switchover planejado
cluster.rejoinInstance('db03:3306');
cluster.rescan();

Tecnologias

MySQLInnoDB ClusterMySQL ShellAdminAPIMySQL RouterClone PluginGroup Replication

Conceito

InnoDB ReplicaSet usa MySQL Shell e MySQL Router para gerenciar uma topologia de replicação assíncrona clássica com um primário e réplicas. É importante ser exato aqui: ReplicaSet não usa Group Replication, não tem consenso, não tem quorum e não faz failover automático. A promoção de uma réplica é uma operação manual, disparada por comando. Em troca, ele não impõe o custo de latência do consenso e roda em cenários onde o Group Replication não é viável.

Como funciona

  • O Shell cria os metadados de topologia e configura a replicação assíncrona entre primário e réplicas, tudo com GTID.
  • O Router lê esses metadados e roteia escrita para o primário e leitura para as réplicas, exatamente como faz no InnoDB Cluster.
  • Não existe eleição. Se o primário morre, o conjunto fica sem destino de escrita até que um humano — ou uma automação externa — execute a promoção.
  • A promoção planejada, com o primário vivo, é segura e ordenada. A promoção forçada, com o primário morto, aceita explicitamente a possibilidade de perda das transações que não chegaram à réplica escolhida.
  • Por ser assíncrono, o RPO no failover não é zero: é exatamente o atraso da réplica no instante da falha.

Na prática

  • Escolher ReplicaSet conscientemente: quando a latência entre nós inviabiliza consenso, ou quando o requisito de disponibilidade admite intervenção.
  • Manter super_read_only nas réplicas para impedir escrita acidental que gere divergência.
  • Monitorar o atraso da réplica como métrica de RPO, e não como métrica de performance — é isso que ela é aqui.
  • Documentar e ensaiar o procedimento de promoção, porque ele será executado sob pressão.
  • Se o requisito for failover automático, a resposta é InnoDB Cluster, não ReplicaSet com um script em volta.

Troubleshooting

SintomaO primário caiu e nada assumiu.
CausaComportamento esperado — ReplicaSet não faz failover automático.
AçãoExecutar a promoção forçada na réplica mais avançada. Se essa espera é inaceitável para o negócio, a topologia escolhida está errada para o requisito.
SintomaApós promoção forçada, faltam transações.
CausaA réplica promovida não tinha recebido tudo — o atraso no instante da falha virou perda de dado.
AçãoComparar gtid_executed do antigo primário, quando ele voltar, com o do novo. Reconciliar é trabalho manual e nem sempre possível: por isso a métrica de atraso precisa ter alerta.
SintomaRéplica não reingressa após voltar.
CausaEla contém transações que o novo primário não tem — divergiu.
AçãoReprovisionar com clone. Não existe merge de histórias divergentes em replicação assíncrona.

Comandos

Criar e popular o ReplicaSet js
var rs = dba.createReplicaSet('dbabrabo_rs');
rs.addInstance('admin@db02:3306', {recoveryMethod: 'clone'});
rs.addInstance('admin@db03:3306', {recoveryMethod: 'clone'});
rs.status();
Promoção planejada e promoção forçada js
// primário vivo — seguro, sem perda
rs.setPrimaryInstance('db02:3306');

// primário morto — assume o risco de perder o que não replicou
rs.forcePrimaryInstance('db02:3306');

Tecnologias

MySQLInnoDB ReplicaSetMySQL ShellMySQL RouterGTIDsuper_read_only

Conceito

Oracle GoldenGate é replicação lógica baseada em captura de log, desacoplada do mecanismo nativo do banco. O Extract lê o log de transações da origem — no MySQL, o Binary Log — e grava as mudanças em arquivos de trail em formato próprio. O Replicat lê o trail no destino e aplica as mudanças. Como o formato intermediário é neutro, origem e destino podem ser bancos diferentes: MySQL para Oracle, Oracle para MySQL, ou qualquer combinação suportada.

Como funciona

  • O Extract se conecta à origem e lê o log de transações, convertendo cada operação em um registro lógico no trail.
  • Os arquivos de trail podem ser transportados para o destino, o que desacopla origem e destino no tempo: uma indisponibilidade do destino não bloqueia a origem enquanto houver trail retido.
  • O Replicat lê o trail e aplica no destino, podendo transformar no caminho — mapear nomes de tabela e coluna, filtrar linhas, converter tipos.
  • Em topologia multi-master, a mesma linha pode ser alterada nos dois lados. O CDR (Conflict Detection and Resolution) define regras determinísticas de quem vence, comparando imagem anterior e posterior.
  • O Parallel Replicat divide a aplicação em múltiplos apply threads respeitando as dependências entre transações — é o mecanismo de throughput.

Na prática

  • Garantir binlog em ROW com imagem completa da linha na origem; sem isso o CDR não tem como comparar valores anteriores.
  • Definir chave de identificação de linha para toda tabela replicada — GoldenGate precisa saber o que identifica unicamente cada linha.
  • Dimensionar a retenção do trail conforme a maior janela de indisponibilidade que o destino pode ter.
  • Estabelecer as regras de CDR antes de ligar multi-master, e não depois do primeiro conflito.
  • Monitorar lag por processo — Extract e Replicat têm atrasos independentes e o gargalo pode estar em qualquer um.
  • Criptografar trail files e credenciais: eles carregam dado de produção em repouso, fora do banco.

Troubleshooting

SintomaReplicat abortando com erro de dado.
CausaRegistro esperado não existe no destino, ou conflito não tratado.
AçãoAnalisar o registro descartado antes de qualquer coisa. Configurar tratamento de exceção é o caminho para não parar a replicação inteira por uma linha, mas os descartes precisam ser revisados, não ignorados.
SintomaLag crescendo só no Replicat.
CausaAplicação serializada no destino, falta de índice, ou contenção de lock.
AçãoAvaliar Parallel Replicat e conferir a indexação das tabelas de destino — o Replicat sofre dos mesmos problemas de qualquer sessão de escrita.
SintomaTrail crescendo sem parar.
CausaDestino parado ou purga não configurada.
AçãoVerificar o estado do Replicat e a política de purga. Trail sem purga enche o filesystem e derruba o Extract junto.
SintomaDivergência silenciosa em multi-master.
CausaRegras de CDR incompletas — existe um caso de conflito que ninguém previu.
AçãoRodar comparação de dados entre os lados periodicamente. Em multi-master, verificação de consistência é rotina, não exceção.

Comandos

Pré-requisito na origem MySQL ini
[mysqld]
log_bin           = /var/lib/mysql/mysql-bin
binlog_format     = ROW
binlog_row_image  = FULL   # imprescindível para CDR
Extract e Replicat, esqueleto text
-- Extract (origem)
EXTRACT emysql
SOURCEDB mysqldb USERIDALIAS ggadmin
EXTTRAIL ./dirdat/em
TABLE vendas.*;

-- Replicat (destino)
REPLICAT rmysql
TARGETDB mysqldb USERIDALIAS ggadmin
MAP vendas.*, TARGET dw.*;
Acompanhar lag dos processos text
GGSCI> INFO ALL
GGSCI> LAG EXTRACT emysql
GGSCI> LAG REPLICAT rmysql
GGSCI> STATS REPLICAT rmysql, TOTALSONLY *

Tecnologias

Oracle GoldenGateExtractReplicatTrail FilesParallel ReplicatCDRReplicação heterogêneaMySQL Binary Log

Conceito

Monitorar replicação é responder duas perguntas separadas: a replicação está funcionando, e quanto dado eu perderia agora. Seconds_Behind_Source responde mal as duas — ele mede a diferença de timestamp do evento em aplicação, zera quando a thread de I/O cai e mente quando há replicação em cascata. A medida confiável combina o conjunto de GTIDs pendentes com a distância entre o que a réplica recebeu e o que ela já aplicou.

Como funciona

  • A thread de I/O e a de aplicação têm atrasos independentes: a réplica pode ter recebido tudo e ainda estar longe de aplicar, ou pode estar aplicando rápido porque parou de receber.
  • GTID_SUBTRACT entre o gtid_executed do source e o da réplica dá o conjunto exato de transações pendentes — é a métrica de RPO.
  • As tabelas de replicação em performance_schema separam status de conexão, de aplicação e de worker, permitindo dizer qual estágio é o gargalo.
  • Um heartbeat na origem, gravado periodicamente em uma tabela dedicada, dá uma medida de atraso em tempo real que não depende de haver tráfego.
  • Em semi-síncrono, o status do plugin precisa ser monitorado à parte: a degradação para assíncrono é silenciosa.

Na prática

  • Alertar sobre thread de replicação parada — separando I/O de aplicação, porque a causa é diferente.
  • Alertar sobre atraso acima do limite de RPO acordado com o negócio, não sobre um número escolhido no chute.
  • Alertar sobre Rpl_semi_sync_source_status quando a topologia depende dessa garantia.
  • Instrumentar heartbeat para distinguir 'sem atraso' de 'sem tráfego'.
  • Verificar consistência de dados periodicamente com checksum de tabela — atraso zero não prova conteúdo igual.

Troubleshooting

SintomaSeconds_Behind_Source igual a zero mas o dado está desatualizado.
CausaThread de I/O parada — a réplica aplicou tudo o que tinha, que é pouco.
AçãoSempre checar Replica_IO_Running junto. Zero de atraso com I/O parada é o pior falso negativo da operação MySQL.
SintomaAtraso oscila muito sem mudança de carga.
CausaTransações grandes sendo aplicadas em bloco, ou DDL longo bloqueando a fila.
AçãoIdentificar a transação em curso nas tabelas de worker. Transação grande em replicação é um problema de design da aplicação.
SintomaRéplica sem erro mas com dado divergente.
CausaDivergência silenciosa acumulada.
AçãoRodar checksum comparativo. Descoberto o desvio, reconstruir — corrigir linha a linha não escala e costuma esconder mais do que resolve.

Comandos

Estado real das threads sql
SELECT SERVICE_STATE FROM performance_schema.replication_connection_status;
SELECT SERVICE_STATE FROM performance_schema.replication_applier_status;

SELECT WORKER_ID, LAST_ERROR_MESSAGE
  FROM performance_schema.replication_applier_status_by_worker;
RPO em transações pendentes sql
SELECT GTID_SUBTRACT(
         '<gtid_executed do source>',
         @@GLOBAL.gtid_executed
       ) AS transacoes_pendentes;

Tecnologias

MySQLperformance_schemaGTID_SUBTRACTHeartbeatChecksum de tabela

Conceito

Quase todo incidente de replicação cai em quatro famílias: a réplica parou com erro, a réplica está viva mas atrasada, a réplica está divergente sem erro, ou o cluster perdeu quorum. Cada família tem um caminho de diagnóstico diferente, e a ação errada — tipicamente pular eventos para 'destravar' — transforma um problema visível em uma divergência invisível que só aparece meses depois, num relatório que não fecha.

Como funciona

  • Primeiro isolar o estágio: recebimento, aplicação ou membership. As três falham por motivos distintos e as métricas são separadas.
  • Com erro na aplicação, o evento que falhou está identificado no status — ler o erro completo é obrigatório antes de qualquer ação.
  • Divergência sem erro só aparece por comparação ativa; nenhum contador vai denunciá-la.
  • Perda de quorum em Group Replication é uma decisão do produto, não uma falha: o grupo se recusa a aceitar escrita para não divergir.
  • Pular evento é aceitável em exatamente um cenário: quando você provou que o efeito da transação já existe no destino. Em qualquer outro caso é criação de divergência.

Na prática

  • Coletar sempre o mesmo conjunto inicial: status das threads, último erro, coordenadas atuais, e o log de erro do período.
  • Reproduzir o efeito da transação problemática em ambiente de teste antes de decidir pular ou reconstruir.
  • Ter um procedimento escrito de reconstrução de réplica e o tempo dela medido — a decisão entre remediar e reconstruir depende desse número.
  • Manter super_read_only nas réplicas para eliminar a causa mais comum de divergência.
  • Registrar todo incidente com causa raiz; replicação que quebra repetidamente é sintoma de outra coisa.

Troubleshooting

SintomaErro 1062, chave duplicada, na réplica.
CausaA linha já existe no destino — escrita local anterior ou reaplicação de evento.
AçãoComparar a linha nos dois lados. Igual em conteúdo, o efeito já está lá e a transação vazia correspondente resolve; diferente, houve divergência e o caminho é reconstruir.
SintomaErro 1032, linha não encontrada, na réplica.
CausaA linha que o UPDATE ou DELETE deveria atingir não existe no destino.
AçãoMesma investigação. Um 1032 isolado costuma ser a ponta de uma divergência maior — vale um checksum da tabela inteira antes de dar o caso por encerrado.
SintomaReplicação para durante DDL longo.
CausaO DDL é aplicado serialmente e bloqueia a fila atrás dele.
AçãoPlanejar DDL em janela, ou usar ferramenta de mudança de schema online que replica em passos pequenos.
SintomaGrupo sem escrita com metade dos nós vivos.
CausaEmpate não é maioria — sem quorum.
AçãoRestabelecer um membro. A reconfiguração forçada só é aceitável com certeza absoluta de que o outro lado está morto, sob risco de dois grupos escrevendo em paralelo.
SintomaRéplica reinicia e volta de um ponto anterior, reaplicando eventos.
CausaMetadados de posição não estavam sendo persistidos de forma transacional.
AçãoUsar armazenamento transacional das informações de replicação e habilitar recuperação automática de posição.

Comandos

Coleta inicial de um incidente sql
SHOW REPLICA STATUS\G

SELECT CHANNEL_NAME, SERVICE_STATE, LAST_ERROR_NUMBER, LAST_ERROR_MESSAGE
  FROM performance_schema.replication_applier_status_by_worker;

SELECT * FROM performance_schema.replication_group_members;
Transação vazia — só com prova de que o efeito já existe sql
-- NAO use isto para 'destravar' replicacao sem investigar.
STOP REPLICA SQL_THREAD;
SET GTID_NEXT = 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee:157';
BEGIN; COMMIT;
SET GTID_NEXT = 'AUTOMATIC';
START REPLICA SQL_THREAD;

Tecnologias

MySQLSHOW REPLICA STATUSperformance_schemaChecksumGroup Replicationsuper_read_only
  • 01 Camadas do servidor e o papel do storage engine
  • 02 Buffer pool: leitura, escrita suja e flush
  • 03 Redo log, LSN e checkpoint
  • 04 Undo, MVCC e read view
  • 05 Níveis de isolamento e o que cada um permite
  • 06 Locks de linha, gap lock e deadlock
  • 07 Estrutura física de tablespace e página
  • 08 Doublewrite buffer e durabilidade
  • 01 Performance Schema: o que instrumentar e o que custa
  • 02 sys schema e as visões que resolvem 80% dos casos
  • 03 EXPLAIN e EXPLAIN ANALYZE
  • 04 Estatísticas, cardinalidade e escolha de índice
  • 05 Índices compostos, ordem das colunas e covering index
  • 06 Slow query log e identificação de padrão
  • 07 Contenção: locks, semáforos e fila de I/O
  • 08 Dimensionamento de buffer pool e memória
  • 01 Backup lógico versus físico: quando cada um
  • 02 XtraBackup: full, incremental e prepare
  • 03 Backup consistente com posição de binlog e GTID
  • 04 Point-in-time recovery aplicando binlog
  • 05 Clone Plugin para provisionamento de réplica
  • 06 Retenção, verificação e teste periódico de restore
  • 07 Recuperação de tabela isolada
  • 08 Documentação do procedimento e RTO medido
  • 01 Usuários, hosts e o modelo de privilégio
  • 02 Roles e menor privilégio na prática
  • 03 TLS obrigatório e certificados
  • 04 TDE: criptografia de tablespace e gestão de chave
  • 05 Audit plugin: o que registrar sem inviabilizar
  • 06 Hardening: contas padrão, arquivos e permissões de SO
  • 07 Gestão de segredos fora do arquivo de configuração
  • 01 Estratégia de upgrade de versão maior
  • 02 Mudança de schema online em tabela grande
  • 03 MySQL Shell e AdminAPI para operação
  • 04 Automação de rotina em Python e Shell
  • 05 Monitoramento: métricas que valem alerta
  • 06 Runbook de incidente e pós-mortem

Stack

Tecnologias abordadas

MySQLInnoDBBinary LogGTIDSemi-syncGroup ReplicationInnoDB ClusterMySQL RouterMySQL ShellXtraBackupPerformance SchemaTDETLS

Investimento

Sob consulta

Os valores são apresentados na conversa inicial, conforme a mentoria escolhida e o formato acordado.

Começa por uma call de diagnóstico.

Mapear onde você está e onde quer chegar antes de montar o plano. Sem compromisso.