Monte um cluster MySQL com 3 nós no Ubuntu 24.04 usando InnoDB Cluster, MySQL Shell e MySQL Router, com failover automático. Veja quando usar o NDB.
Ter o MySQL em vários servidores (multi-node) serve para uma coisa principal: o banco continuar no ar quando uma máquina cai. Existem quatro caminhos, e escolher o certo evita muito retrabalho:
| Solução | Como funciona | Quando usar |
|---|---|---|
| InnoDB Cluster (MySQL) | 3 a 9 servidores com Group Replication; um primário grava, os outros acompanham; troca automática se o primário cair | Sites e sistemas comuns que precisam de alta disponibilidade. É o tema deste guia. |
| NDB Cluster (MySQL) | Produto separado, com motor próprio (NDBCLUSTER) e dados distribuídos entre nós de dados | Cargas muito específicas, com volume enorme de gravações curtas e exigência extrema de disponibilidade |
| Galera Cluster (MariaDB) | Síncrono, todos os nós aceitam gravação | Quem usa MariaDB; veja o guia do Galera |
| Replicação origem-réplica | Cópia assíncrona, troca manual | Cópia quente, relatórios e backup; veja o guia de replicação |
Versões antigas deste artigo usavam o NDB Cluster. Hoje, para a maioria das aplicações web, o InnoDB Cluster é a escolha natural: usa o InnoDB que suas tabelas já usam, e a aplicação não precisa mudar.
Como o InnoDB Cluster funciona
- Três servidores MySQL formam o grupo. Um é o primário (leitura e gravação) e os outros são secundários (só leitura), sempre sincronizados. Com três nós, o cluster aguenta a queda de um.
- MySQL Shell (
mysqlsh) é a ferramenta que configura e administra o cluster. - MySQL Router roda no servidor da aplicação. A aplicação conecta nele, e ele encaminha para o primário atual: porta
6446para leitura e gravação,6447para só leitura. Quando o primário muda, o Router acompanha sozinho.
Antes de começar
- Três servidores Ubuntu 24.04 para o banco:
db1(10.0.0.31),db2(10.0.0.32) edb3(10.0.0.33), mais o servidor da aplicação (10.0.0.40). - Todas as tabelas em InnoDB e com chave primária. O cluster recusa tabelas sem chave primária.
- Nomes resolvendo para o IP da rede privada em todas as máquinas. Edite o
/etc/hostsde cada uma:
No Ubuntu, apague ou comente a linha10.0.0.31 db1 10.0.0.32 db2 10.0.0.33 db3127.0.1.1 db1(com o nome da própria máquina) que vem de fábrica. Ela faz o servidor anunciar um endereço de loopback, e o cluster não funciona. - Firewall: com a configuração padrão, o grupo conversa pela própria porta 3306. Libere 3306 e 33060 entre os nós e do servidor da aplicação:
sudo ufw allow from 10.0.0.0/24 to any port 3306,33060 proto tcp
Passo 1: instale o MySQL 8.4 LTS nos três nós
O Ubuntu 24.04 traz o MySQL 8.0, cuja série saiu do suporte da Oracle em abril de 2026. Para um cluster novo, use o repositório oficial da Oracle com uma série LTS:
- Baixe o pacote de configuração do repositório em dev.mysql.com/downloads/repo/apt (arquivo
mysql-apt-config_*_all.deb). - Instale e escolha a série mysql-8.4-lts (ou a LTS mais nova oferecida) na tela que aparece:
Defina uma senha forte para o root quando o instalador pedir.sudo dpkg -i mysql-apt-config_*_all.deb sudo apt update sudo apt install -y mysql-server mysql-shell
Passo 2: prepare cada instância
Em cada um dos três nós, abra o MySQL Shell e rode o assistente de configuração. Ele cria o usuário administrador do cluster e ajusta o que falta (GTID, IDs, etc.):
mysqlsh root@localhost
dba.configureInstance('root@localhost:3306', {clusterAdmin: 'clusteradmin'})
O Shell pede a senha do novo usuário clusteradmin (use a mesma nos três nós), mostra as mudanças e pergunta se pode aplicá-las e reiniciar o MySQL. Responda y. Se algo impedir, a mensagem diz exatamente o quê.
Passo 3: crie o cluster e adicione os nós
Conecte no db1 com o usuário administrador e crie o cluster:
mysqlsh clusteradmin@db1
var cluster = dba.createCluster('loja')
cluster.addInstance('clusteradmin@db2:3306', {recoveryMethod: 'clone'})
cluster.addInstance('clusteradmin@db3:3306', {recoveryMethod: 'clone'})
cluster.status()
O método clone copia os dados do primário para o nó novo, apagando o que houver nele. No fim, o cluster.status() deve mostrar um nó PRIMARY, dois SECONDARY, todos ONLINE, e a frase de que o cluster tolera uma falha.
mysqlsh clusteradmin@db1 e rode var cluster = dba.getCluster().Passo 4: instale o MySQL Router no servidor da aplicação
No servidor da aplicação, configure o mesmo repositório da Oracle e:
sudo apt install -y mysql-router
sudo mysqlrouter --bootstrap clusteradmin@db1:3306 --user=mysqlrouter
sudo systemctl restart mysqlrouter
O --bootstrap lê a topologia do cluster e gera a configuração em /etc/mysqlrouter/. Agora aponte a aplicação para 127.0.0.1, porta 6446, com um usuário de aplicação criado no primário (os comandos de CREATE USER e GRANT são replicados para os outros nós).
Passo 5: teste o failover
- Desligue o primário: no
db1,sudo systemctl stop mysql. - Veja a eleição: conecte no
db2(mysqlsh clusteradmin@db2), rodedba.getCluster().status()e confira que outro nó virouPRIMARY. A aplicação, pela porta 6446, continua gravando. - Religue o db1:
sudo systemctl start mysql. Ele volta sozinho ao grupo como secundário.
E o MySQL NDB Cluster?
O NDB Cluster é outro produto, com binários próprios. Ele tem um nó de gerenciamento (ndb_mgmd), nós de dados (ndbd ou ndbmtd) que guardam as tabelas divididas entre si, e nós SQL (mysqld) que atendem as consultas. As tabelas precisam usar ENGINE=NDBCLUSTER, com limites diferentes do InnoDB, e uma instalação com redundância real costuma ocupar quatro ou mais máquinas. Só vale a pena quando a aplicação foi pensada para ele. A referência é a documentação oficial do NDB Cluster.
Problemas comuns
O Shell diz que o nome do servidor resolve para 127.0.1.1
É a linha padrão do /etc/hosts do Ubuntu. Remova-a e deixe o nome apontando para o IP privado, ou defina report_host = 10.0.0.31 (o IP do próprio nó) na seção [mysqld] e reinicie.
The following tables do not have a Primary Key or equivalent column
O cluster precisa de chave primária em todas as tabelas. Crie uma (por exemplo, uma coluna id com AUTO_INCREMENT) nas tabelas listadas e tente de novo.
O nó tem transações que não existem no cluster (errant GTIDs)
Alguém gravou direto naquele servidor. Use recoveryMethod: 'clone' no addInstance para substituir os dados dele pelos do cluster.
Dois nós caíram e o cluster parou de aceitar gravações
Sem maioria, o nó restante bloqueia gravações para não divergir. Quando tiver certeza de que os outros estão realmente fora, force o quórum pelo nó vivo: cluster.forceQuorumUsingPartitionOf('clusteradmin@db1:3306'). Se todos os nós foram desligados, religue o MySQL neles e rode dba.rebootClusterFromCompleteOutage() em um deles.