Backup MySQL com mysqldump e Restaurar Banco de Dados no Linux
Aprenda a fazer backup MySQL com mysqldump e restaurar banco de dados no Linux com comandos prontos, consistência transacional e validação.
Perder um banco MySQL por dropar tabela errada, corromper arquivo de dados
ou subir migration ruim acontece com qualquer time. A diferença entre
incidente curto e dia inteiro de pânico é ter backup recente, validado e
restaurável. Este tutorial cobre o fluxo completo de backup com
mysqldump e restore subsequente, incluindo os flags que realmente
importam em produção.
O foco aqui é prático: comandos prontos pra copiar, parâmetros explicados no contexto e validação do arquivo gerado antes que você precise dele de verdade. A persona é developer que conhece MySQL básico (SELECT/INSERT) mas nunca configurou rotina de backup própria — provavelmente migrando de hospedagem compartilhada pra uma VPS própria onde a responsabilidade agora é sua.
Tempo estimado: 15-20 minutos pra executar o tutorial completo num banco de exemplo. Em produção real, o dump em si demora proporcional ao tamanho do banco (~1 GB/min em SSD NVMe típico).
Pré-requisitos
Ubuntu 22.04 LTS ou 24.04 LTS (Debian também serve) com MySQL 8.0 ou
MariaDB 10.6+ instalado e rodando. Acesso sudo no servidor e credenciais
do usuário root do MySQL ou de um usuário com privilégios SELECT,
LOCK TABLES, SHOW VIEW e EVENT no banco que vai ser dumpado.
Espaço livre em disco no mínimo igual ao tamanho do banco (verifique com
df -h).
Pra confirmar que o mysqldump está disponível, rode:
mysqldump --version
A saída deve mostrar algo como mysqldump Ver 8.0.x for Linux on x86_64.
Se o comando não for encontrado, instale o pacote client:
sudo apt update
sudo apt install -y mysql-client
Pra MariaDB, o binário equivalente é o próprio mariadb-dump (alias de
mysqldump em distribuições recentes).
Backup do banco com mysqldump
O mysqldump lê o estado atual do MySQL e gera um arquivo SQL com todos
os comandos necessários pra recriar o banco do zero — CREATE DATABASE,
CREATE TABLE, INSERT de cada linha, triggers, views e procedures. É um
formato portátil e versionável (você pode até commitar no Git, embora
não seja o uso primário).
Faça o dump simples de um banco específico:
mysqldump -u root -p meubanco > meubanco-2026-05-29.sqlO -u root define o usuário, -p pede a senha interativamente (mais
seguro que passar -psenha na linha de comando, que vaza no histórico
do shell e em ps aux). O redirecionamento > salva a saída no arquivo
nomeado.
Inclua a data no nome do arquivo desde o começo — ajuda na rotação e evita sobrescrita acidental.
Adicione os flags de consistência transacional pra produção:
mysqldump -u root -p \
--single-transaction \
--routines \
--triggers \
--events \
--quick \
meubanco > meubanco-2026-05-29.sqlO --single-transaction envolve o dump em START TRANSACTION com
isolation REPEATABLE READ, gerando um snapshot consistente sem
bloquear escritas em tabelas InnoDB. Esse é o flag crítico em produção:
sem ele, escritas paralelas podem deixar o dump inconsistente.
Os flags --routines, --triggers e --events incluem stored
procedures, triggers e eventos agendados — coisas que são fáceis de
esquecer e que você só percebe que faltam quando restaura e o sistema
quebra. --quick faz o dump linha-por-linha em vez de carregar tabelas
inteiras em RAM, importante pra tabelas grandes.
Comprima na hora pra economizar espaço:
mysqldump -u root -p \
--single-transaction --routines --triggers --events --quick \
meubanco | gzip > meubanco-2026-05-29.sql.gzO pipe pra gzip reduz o arquivo em 70-85% pra dumps típicos (texto SQL
comprime muito bem). Pra bancos de 10 GB, isso é diferença entre 2 GB
e 10 GB ocupando seu disco de backup.
Pra compressão melhor (mais lenta), troque gzip por zstd -19 ou
xz -9.
Faça backup de todos os bancos de uma vez (útil pra snapshot diário do servidor inteiro):
mysqldump -u root -p \
--all-databases \
--single-transaction \
--routines --triggers --events \
--master-data=2 \
| gzip > full-2026-05-29.sql.gzO --all-databases inclui também os bancos do sistema (mysql,
sys, performance_schema) — preserva usuários e grants. O
--master-data=2 grava a posição do binlog no dump como comentário,
útil pra point-in-time recovery se você tiver binlogs habilitados.
Pra evitar digitar senha em scripts automatizados, crie ~/.my.cnf com
[client] + user=root + password=senha e permissão 600
(chmod 600 ~/.my.cnf). O mysqldump lê automaticamente — você roda
mysqldump meubanco > arquivo.sql sem -u nem -p. Nunca coloque
senha em script versionado.
Validação do arquivo de backup
Backup que você nunca testou restaurar é boato, não backup. Antes de confiar no arquivo, valide três coisas: integridade do arquivo, sintaxe SQL e que o dump cobre o que você espera.
Verifique se o arquivo não foi truncado:
ls -lh meubanco-2026-05-29.sql.gz
gzip -t meubanco-2026-05-29.sql.gz && echo "OK: arquivo íntegro"O gzip -t testa a integridade da compressão sem descomprimir. Se
falhar, o arquivo está corrompido (geralmente disco cheio durante o
dump ou crash no meio). Re-rode o dump.
Confira o conteúdo do dump:
zcat meubanco-2026-05-29.sql.gz | head -30
zcat meubanco-2026-05-29.sql.gz | grep -c "^INSERT INTO"
zcat meubanco-2026-05-29.sql.gz | grep "^CREATE TABLE" | wc -lO head mostra o cabeçalho com versão do mysqldump e configurações.
O grep -c INSERT conta linhas de insert (sanity check de volume de
dados). O grep CREATE TABLE | wc -l conta tabelas — bate com o que
você espera ter no banco?
Pra comparar com o servidor original:
mysql -u root -p -e "SELECT COUNT(*) AS tabelas FROM information_schema.tables WHERE table_schema='meubanco';"Os números devem coincidir.
Restaurar banco de dados a partir do dump
Restore é o caminho inverso: ler o arquivo SQL e enviar pro servidor MySQL que executa cada comando em sequência. Isso pode ser num servidor novo, no mesmo servidor após drop acidental, ou pra clonar dados de produção pra ambiente de staging.
Crie o banco vazio de destino (só se ainda não existir):
mysql -u root -p -e "CREATE DATABASE meubanco CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"Use utf8mb4 sempre — suporta emoji e caracteres asiáticos completos.
Pular esse passo é OK se o dump foi feito com --databases (que
inclui o CREATE DATABASE no arquivo) ou --all-databases.
Restaure o dump comprimido direto via pipe:
zcat meubanco-2026-05-29.sql.gz | mysql -u root -p meubancoO zcat descomprime na memória e envia pro mysql client, que executa
cada comando contra o banco meubanco. Pra arquivo .sql não
comprimido, use redirecionamento:
mysql -u root -p meubanco < meubanco-2026-05-29.sqlA operação demora proporcional ao tamanho (cada INSERT roda
individualmente por padrão). Pra dumps grandes, deixe rodando em
tmux ou screen pra não interromper se a sessão SSH cair.
Acompanhe o progresso em dumps grandes:
pv meubanco-2026-05-29.sql.gz | zcat | mysql -u root -p meubancoO pv (pipe viewer) mostra barra de progresso e velocidade. Instale
com sudo apt install -y pv. Sem ele, o restore roda silencioso — você
não sabe se está em 10% ou 90%.
Se o banco já tem tabelas, o dump (que contém DROP TABLE IF EXISTS)
vai apagar as versões atuais e recriar. Em produção, faça o restore num
banco com nome diferente primeiro (meubanco_restore) e valide antes
de promover via RENAME.
Verificação pós-restore
Restore que não foi verificado é meio restore. Cheque três coisas: as tabelas voltaram, a contagem de linhas bate e a aplicação consegue abrir conexão.
Confirme estrutura e contagens:
mysql -u root -p meubanco -e "SHOW TABLES;"
mysql -u root -p meubanco -e "SELECT COUNT(*) FROM usuarios;"A primeira lista as tabelas; a segunda conta linhas numa tabela que você sabe quantas linhas tinha antes. Discrepâncias indicam dump incompleto (faltou flag) ou restore interrompido.
--single-transaction --routines --triggers --quick --master-data=2 Resolução de problemas
Erro “Access denied” durante o dump
O usuário não tem privilégio em alguma tabela. Verifique grants com
SHOW GRANTS FOR 'usuario'@'localhost';. Pra dump completo, o usuário
precisa de SELECT, LOCK TABLES, SHOW VIEW, EVENT e
TRIGGER. A solução mais simples é rodar como root.
Restore falha com “Unknown collation utf8mb4_0900_ai_ci”
O dump foi feito em MySQL 8.0+ e você está restaurando em 5.7 ou
MariaDB antigo. Edite o arquivo (sed -i 's/utf8mb4_0900_ai_ci/utf8mb4_unicode_ci/g' arquivo.sql)
ou regere o dump com --compatible=mysql57.
”MySQL server has gone away” no meio do restore
max_allowed_packet muito pequeno no servidor de destino. Aumente em
/etc/mysql/mysql.conf.d/mysqld.cnf com max_allowed_packet = 256M,
reinicie o MySQL e tente de novo.
Próximos passos
Backup manual é o começo — automatize com cron e copie pra storage externa (rclone pra B2/S3 funciona bem). Considere também replicação master-slave pra ter cópia quente disponível em segundos, e habilite binary logs pra point-in-time recovery dentro do dia.
Se você está rodando MySQL em produção, uma VPS Hostini já vem
com SSD NVMe e snapshots de disco como camada adicional de proteção
sobre o backup lógico do mysqldump — recovery rápido pra desastres
de infraestrutura, sem substituir o dump SQL que é portátil entre
servidores.
Perguntas frequentes
Qual a diferença entre mysqldump e snapshot do disco?
mysqldump gera um arquivo SQL portátil (texto com CREATE TABLE e INSERTs), restaurável em qualquer servidor MySQL compatível, inclusive em versão diferente. Snapshot de disco é uma cópia binária — mais rápida em bancos grandes, mas só restaura no mesmo motor/versão e exige cuidado com transações em voo. Pra bancos abaixo de 50 GB, mysqldump é o padrão.
mysqldump trava as tabelas durante o backup?
Por padrão sim, com FLUSH TABLES WITH READ LOCK em MyISAM. Em InnoDB, use --single-transaction pra fazer o dump dentro de uma transação consistente sem bloquear escritas. Esse é o flag mais importante pra bancos em produção.
Posso restaurar o dump em uma versão diferente do MySQL?
Sim, desde que vá da versão mais antiga pra mais nova (5.7 → 8.0, por exemplo). O reverso pode falhar por sintaxe nova não suportada. Pra cross-version downgrade, gere o dump com --compatible=mysql57 no servidor mais novo.
Como faço backup só de algumas tabelas?
Passe os nomes das tabelas após o nome do banco: mysqldump -u root -p meubanco usuarios pedidos > parcial.sql. Isso dumpa só usuarios e pedidos do banco meubanco. Útil pra migrar dados específicos sem mover o banco inteiro.
O arquivo .sql ficou enorme — como reduzir?
Comprima com gzip no pipe: mysqldump ... | gzip > backup.sql.gz. A compressão tipicamente reduz 70-85% do tamanho. Pra restaurar, use zcat backup.sql.gz | mysql -u root -p meubanco. Evita ocupar espaço temporário em disco durante a operação.
Como agendar o backup pra rodar todo dia automaticamente?
Use cron: crie /etc/cron.daily/mysql-backup com o script de dump e rotação. Grave a senha em ~/.my.cnf com permissão 600 pra não passar em linha de comando. Combine com rsync ou rclone pra copiar pra storage externa logo após o dump.