
💾 Fazer backup e restaurar uma base de dados MySQL via PHP
Perder uma base de dados significa perder encomendas, utilizadores e conteúdo em segundos. Para o proprietário de um site WordPress, o backup não é «bom de ter», é obrigatório. Mas iniciar sessão manualmente no phpMyAdmin todos os dias é uma perda de tempo e, quando precisa dele, o backup simplesmente não está lá.
Um script PHP resolve o problema: fornece-lhe o acesso à base de dados e ele exporta a estrutura e os dados para um ficheiro SQL. Em cinco minutos de configuração, obtém um backup programável e repetível que não se esquecerá de fazer.
A seguir: scripts prontos a usar para backup e restauro de MySQL em PHP. Vamos detalhar como funcionam, onde obter as credenciais e como executar o backup automático de forma programada para que a sua base de dados nunca fique desprotegida.
💡 Visão geral rápida:
- Ligar ao MySQL via
mysqli, obter a lista de tabelas e exportar a estrutura - Criar o dump SQL:
CREATE TABLEmaisINSERTpara cada tabela, guardar em ficheiro - Restaurar: ler o dump e executar as consultas num lote via
mysqli_multi_query - A automatização via Cron (Linux) ou Agendador de Tarefas (Windows) executa o script sem a sua intervenção
- A compressão para
.gze a rotação de cópias antigas poupam espaço e mantêm o histórico de backups
Passo 1: Credenciais e ambiente, o que precisa antes de executar
Antes de escrever código, reúna três coisas: credenciais MySQL, um diretório para armazenar os backups e uma noção de onde o script será executado.
Para se ligar à base de dados precisa do host (normalmente localhost ou 127.0.0.1), nome de utilizador, palavra-passe e nome da base de dados. Num site WordPress, estes dados residem no wp-config.php: as constantes DB_HOST (servidor), DB_USER (utilizador), DB_PASSWORD (palavra-passe) e DB_NAME (nome da base de dados).
Crie o diretório de backup fora da pasta pública do site. Coloque a pasta backups/ um nível acima de public_html, para que os ficheiros SQL não fiquem acessíveis a partir do navegador. As permissões de escrita (chmod 755 ou chmod 775) são obrigatórias: sem elas, o fopen() e o fwrite() falharão com um erro.
O script PHP é executado a partir da linha de comandos: php backup.php. A execução via web (através do navegador) também é possível, mas a linha de comandos é mais segura, ninguém adivinhará o URL do script e fará o dump da sua base de dados.
Passo 2: Script PHP para backup da base de dados
O script faz três passagens: obtém a lista de tabelas, para cada uma exporta a estrutura (SHOW CREATE TABLE) e depois os dados (SELECT *). O resultado é reunido numa única string e escrito num ficheiro .sql. Guarde o código como backup.php e execute-o a partir do terminal.
1 <?php 2 3 $connection = mysqli_connect('localhost', 'user', 'pass', 'my_database'); 4 5 if (!$connection) { 6 die('Ошибка подключения: ' . mysqli_connect_error()); 7 } 8 9 $tables = []; 10 $result = mysqli_query($connection, "SHOW TABLES"); 11 while ($row = mysqli_fetch_row($result)) { 12 $tables[] = $row[0]; 13 } 14 15 $dump = ''; 16 foreach ($tables as $table) { 17 $dump .= 'DROP TABLE IF EXISTS ' . $table . ";\n"; 18 19 $create = mysqli_query($connection, "SHOW CREATE TABLE " . $table); 20 $row = mysqli_fetch_row($create); 21 $dump .= $row[1] . ";\n\n"; 22 23 $data = mysqli_query($connection, "SELECT * FROM " . $table); 24 $num_fields = mysqli_num_fields($data); 25 26 while ($row = mysqli_fetch_row($data)) { 27 $dump .= "INSERT INTO " . $table . " VALUES("; 28 for ($j = 0; $j < $num_fields; $j++) { 29 if (isset($row[$j])) { 30 $row[$j] = mysqli_real_escape_string($connection, $row[$j]); 31 $dump .= '"' . $row[$j] . '"'; 32 } else { 33 $dump .= 'NULL'; 34 } 35 if ($j < $num_fields - 1) { 36 $dump .= ','; 37 } 38 } 39 $dump .= ");\n"; 40 } 41 $dump .= "\n\n"; 42 } 43 44 $filename = 'backups/dump_' . date('Y-m-d_H-i-s') . '.sql'; 45 $handle = fopen($filename, 'w+'); 46 fwrite($handle, $dump); 47 fclose($handle); 48 49 echo "Бэкап сохранён: " . $filename . "\n"; 50 51 ?>
O que acontece aqui, linha a linha. O mysqli_connect() abre uma ligação; se o acesso for negado, o script termina com uma mensagem clara em vez de continuar silenciosamente. O ciclo SHOW TABLES recolhe os nomes das tabelas para um array.
Para cada tabela, o SHOW CREATE TABLE devolve exatamente uma linha, sendo o segundo campo a consulta DDL completa. Adicionamos DROP TABLE IF EXISTS antes dela para que o dump possa ser aplicado a uma base de dados limpa sem conflitos.
O SELECT * lê todas as linhas. A função mysqli_real_escape_string() escapa aspas e caracteres especiais dentro dos valores; ao contrário de addslashes(), respeita a codificação da ligação e não deixa passar injeções através de sequências multibyte. Os valores NULL são inseridos como NULL, não como string vazia.
O nome do ficheiro contém a data e hora de execução, o que é conveniente para a rotação. O ficheiro é aberto em modo w+ (criar ou sobrescrever) e recebe o dump completo numa única operação fwrite().
Passo 3: Script para restauro da base de dados a partir do dump SQL
O script inverso lê o ficheiro .sql e executa as consultas na base de dados. Na prática, os dumps pesam frequentemente dezenas de megabytes, pelo que file_get_contents() e explode por ; não é a melhor opção para produção. Mas para fins de aprendizagem e bases de dados pequenas, a abordagem funciona.
Guarde como restore.php. Antes de executar, faça um backup completo da base de dados atual; o restauro sobrescreve as tabelas.
1 <?php 2 3 $connection = mysqli_connect('localhost', 'root', '', 'test'); 4 5 if (!$connection) { 6 die('Ошибка подключения: ' . mysqli_connect_error()); 7 } 8 9 $filename = 'backups/dump_2026-06-14_12-00-00.sql'; 10 11 if (!file_exists($filename)) { 12 die('Файл дампа не найден: ' . $filename); 13 } 14 15 $contents = file_get_contents($filename); 16 17 if (mysqli_multi_query($connection, $contents)) { 18 do { 19 if ($result = mysqli_store_result($connection)) { 20 mysqli_free_result($result); 21 } 22 } while (mysqli_next_result($connection)); 23 echo "База восстановлена из: " . $filename . "\n"; 24 } else { 25 echo "Ошибка восстановления: " . mysqli_error($connection) . "\n"; 26 } 27 28 mysqli_close($connection); 29 30 ?>
A diferença chave em relação ao mysqli_query() linha a linha é o mysqli_multi_query(). Este aceita uma string com várias consultas SQL e executa-as sequencialmente numa única chamada. O ciclo do...while com mysqli_next_result() é obrigatório: sem ele, as consultas subsequentes não serão executadas e a ligação ficará pendurada.
O mysqli_store_result() obtém o resultado da consulta atual e o mysqli_free_result() liberta a memória. Se a consulta for INSERT ou CREATE TABLE, o resultado será false, e isso é normal: o script simplesmente passa para a seguinte.
Nota: o script não faz DROP DATABASE nem recria a própria base de dados. Ele espera que a base de dados test já exista. Por segurança, a primeira linha do dump pode conter CREATE DATABASE IF NOT EXISTS.
Passo 4: Automatização do backup via Cron e compressão
A execução manual funciona para tarefas pontuais. Mas num site ativo, o backup deve acontecer sem si, todas as noites enquanto dorme.
Num servidor Linux, adicione uma tarefa ao Cron: crontab -e e a linha 0 3 * * * php /path/to/backup.php executa o script todos os dias às 3 da manhã. No Windows, o Agendador de Tarefas com a ação «iniciar um programa» php.exe e o argumento-caminho para o script.
Duas melhorias que transformam um script de aprendizagem num pronto para produção:
Compressão. Após escrever o ficheiro .sql, adicione exec("gzip " . $filename);, o tamanho do dump diminuirá 5 a 10 vezes. Para o restauro, o gunzip descomprime o ficheiro de volta.
Rotação. Mantenha os backups dos últimos 7 dias e elimine o resto. Opção simples: adicione a limpeza de ficheiros com mais de N dias ao início do script:
1 $retention_days = 7; 2 $backup_dir = 'backups/'; 3 foreach (glob($backup_dir . '*.sql.gz') as $file) { 4 if (filemtime($file) < time() - $retention_days * 86400) { 5 unlink($file); 6 } 7 }
Como resultado, tem um sistema autónomo: o script é executado de forma programada, cria um backup comprimido com a data no nome do ficheiro e limpa o material antigo. Mãos experientes e 20 minutos de configuração substituem um plugin pago.
O vídeo acima mostra o ciclo completo de backup automático: do ficheiro de configuração à verificação do .sql.gz comprimido na pasta backups/. A abordagem é exatamente a mesma descrita neste artigo, com verificações de erro e registo adicionais.
⁉️🤔 FAQ
É seguro guardar a palavra-passe do MySQL num script PHP?
Armazenar credenciais em texto simples dentro de um script só é aceitável se o ficheiro residir fora do diretório público do site e estiver inacessível a partir do navegador. É melhor mover as credenciais para um
config.phpseparado, fora depublic_html, e incluí-lo viarequire. Ainda mais fiável: passe a palavra-passe através de uma variável de ambiente:getenv('DB_PASS').
Posso fazer backup apenas de tabelas específicas?
Sim. Substitua
SHOW TABLESpor um array explícito de nomes:$tables = ['wp_posts', 'wp_postmeta', 'wp_options'];. Ou exclua tabelas não importantes viaif (!in_array($table, ['wp_litespeed_cache', 'wp_actionscheduler_logs'])). Na prática, as tabelas de cache e de logs ocupam uma parte significativa do tamanho da base de dados e não são necessárias para o restauro.
Quanto espaço ocupa um backup da base de dados de um site WordPress médio?
Um dump SQL não comprimido de uma base de dados com 500 artigos e 15 plugins pesa entre 15 e 40 MB. Após
gzip, entre 2 e 8 MB. Ao longo de um mês de backups diários com compressão, acumulam-se 100 a 300 MB; para um servidor com 20 GB de disco, isto é negligenciável. A rotação para 7 dias mantém o espaço ocupado entre 50 e 100 MB.
O que fazer se o ficheiro de backup estiver corrompido?
Antes de restaurar, verifique a integridade:
gunzip -t dump.sql.gzpara comprimido,head -n 20 dump.sqlpara não comprimido; certifique-se de que o ficheiro começa com comentários SQL, não com lixo binário. Não restaure um dump corrompido, pois perderá dados. É exatamente por isso que mantém pelo menos 2 ou 3 das cópias mais recentes.
Em que difere esta abordagem dos plugins de backup para WordPress?
Um plugin como o UpdraftPlus oferece uma interface web, backups incrementais e envio para a nuvem «pronto a usar». Um script PHP é o controlo total sobre o processo, sem código extra no admin. Para um programador que já trabalha com o servidor, o script é mais rápido e transparente. Para um cliente sem acesso à consola, um plugin é mais conveniente.
Script manual, mysqldump ou plugin: o que escolher para a sua tarefa
Um script de backup em PHP dá-lhe o principal: a compreensão exata do que acontece à sua base de dados durante o backup. Não confia numa caixa negra, controla cada consulta.
Se o site está em produção e a velocidade é importante, use o mysqldump. Um único comando mysqldump -u user -p db_name | gzip > dump.sql.gz faz o mesmo, mas muitas vezes mais rápido, porque trabalha ao nível do motor do MySQL, e não com SELECT linha a linha. Um script PHP é para fins de aprendizagem, cenários personalizados (fazer backup não de toda a base de dados, mas dos resultados de uma consulta específica) e ambientes onde o mysqldump não está disponível.
Se o site está em WordPress e não quer mergulhar na consola, qualquer plugin de backup resolverá a tarefa sem código. O UpdraftPlus, o BackWPup, o Duplicator capturam tanto a base de dados como os ficheiros do site.
Comece com um script manual, perceba como um dump SQL é formado. Depois, configure o Cron e a compressão. Último passo: verifique o restauro num servidor de teste; um backup sem verificação de restauro não é considerado concluído. Que ferramenta usa para o backup da base de dados? Escreva nos comentários.



