Fazer o backup do banco de dados é uma tarefa essencial para recuperar o sistema após um crash de hardware, ataque hacker, invasão alienígena etc...
Pensando nisso estou colocando nas minhas aplicações um botão de backup para que o usuário final possa fazer ele mesmo um backup do banco de dados e salvar em um Pendrive, mandar por e-mail para ele mesmo, ou mandar imprimir em formulário contínuo pra ver se chega na lua, sei lá.
Procurei um bom tanto na internet não achei algo que fosse 100% o que eu queria mas achei algo próximo que me ajudou a lot em http://www.devmedia.com.br/post-3925-Fazendo-backup-de-Mysql-atraves-de-PHP.html
Problema: se um usuário colocasse uma string com um ' no meio, ele fecha a string do sql que usa ' para delimitar a string.
Para isso escapamos as single-quotes ou aspas simples ' com um backslash ou barra invertida \ antes.
Um erro parecido acontece se no banco houver uma string que termina com backslash, pois isso anularia a single quote que fecha a string, então antes de backslash, deve-se colocar outro backslash.
Sem entrar em maiores detalhes sobre ordem dos fatores fiz uma outra adção para quem usa UTF-8 e quer validar os caracteres, erros com importações mal feitas podem ocasionar alguns erros na geração do script esse $checkUtf, se true remove caracteres que não sejam UTF-8 evitando esse pau.
Segue o código, com certeza aceito comentários e sugestões de melhoria.
<?php
// código baseado em http://www.devmedia.com.br/post-3925-Fazendo-backup-de-Mysql-atraves-de-PHP.html
// com melhorias dos comentários do mesmo post
// com adicional de escape string por Marcos Fedato marcosfedato.blogspot.com.br
// com checagem de caracteres UTF-8 por http://stackoverflow.com/questions/1401317/remove-non-utf8-characters-from-string
$usuario = "user";
$senha = "123";
$dbname = "mydb";
// use true se quiser remover caracteres que não sejam utf-8
$checkUtf = false;
// conectando ao banco
mysql_connect("localhost", $usuario, $senha) or die(mysql_error());
mysql_select_db($dbname) or die(mysql_error());
// gerando um arquivo sql. Como?
// a função fopen, abre um arquivo, que no meu caso, será chamado como: nomedobanco.sql
// note que eu estou concatenando dinamicamente o nome do banco com a extensão .sql.
$back = fopen($dbname . ".sql", "w");
// aqui, listo todas as tabelas daquele banco selecionado acima
$res = mysql_list_tables($dbname) or die(mysql_error());
// ultra importante para não dar erro nos primeiros inserts
// principalmente de usar InnoDB e relacionar as tabelas
fwrite($back, "set foreign_key_checks=0;\n\n");
// regex para ver se o char é UTF-8
// Link: http://stackoverflow.com/questions/1401317/remove-non-utf8-characters-from-string
$regex1 = <<<'END'
/
( [\x00-\x7F] # single-byte sequences 0xxxxxxx
| [\xC0-\xDF][\x80-\xBF] # double-byte sequences 110xxxxx 10xxxxxx
| [\xE0-\xEF][\x80-\xBF]{2} # triple-byte sequences 1110xxxx 10xxxxxx * 2
| [\xF0-\xF7][\x80-\xBF]{3} # quadruple-byte sequence 11110xxx 10xxxxxx * 3
)
| . # anything else
/x
END;
// resgato cada uma das tabelas, num loop
while ($row = mysql_fetch_row($res))
{
$table = $row[0];
// usando a função SHOW CREATE TABLE do mysql, exibo as funções de criação da tabela,
// exportando também isso, para nosso arquivo de backup
$res2 = mysql_query("SHOW CREATE TABLE $table");
// digo que o comando acima deve ser feito em cada uma das tabelas
while ($lin = mysql_fetch_row($res2)) {
// instruções que serão gravadas no arquivo de backup
fwrite($back, "\n#\n# Criação da Tabela : $table\n#\n\n");
fwrite($back, "$lin[1] ;\n\n#\n# Dados a serem incluídos na tabela\n#\n\n");
// seleciono todos os dados de cada tabela pega no while acima
// e depois gravo no arquivo .sql, usando comandos de insert
$res3 = mysql_query("SELECT * FROM $table");
$first = true;
while ($r = mysql_fetch_row($res3))
{
if ($first)
{
$sql = "INSERT INTO $table VALUES ";
$first = false;
}
else
{
$sql .= ',';
}
$sql .= "('";
$imploded = '';
$firstImplode = true;
foreach ($r as $reg)
{
if ($firstImplode)
{
$firstImplode = false;
}
else
{
$imploded .= "', '";
}
if ($checkUtf)
{
$escaped = str_replace('\'', "\\'", str_replace('\\', "\\\\", preg_replace($regex1, '$1', $reg)));
}
else
{
$escaped = str_replace('\'', "\\'", str_replace('\\', "\\\\", $reg));
}
$imploded .= $escaped;
}
$sql .= $imploded;
$sql .= "')\n";
}
if (!$first)
{
$sql .= ";\n";
fwrite($back, $sql);
}
}
}
// fechar o arquivo que foi gravado
fclose($back);
// gerando o arquivo para download, com o nome do banco e extensão sql.
$arquivo = $dbname . ".sql";
Header("Content-type: application/sql");
Header("Content-Disposition: attachment; filename=$arquivo");
// lê e exibe o conteúdo do arquivo gerado
readfile($arquivo);
?>
Olá, Marcos, tudo bem? Espero que sim!
ResponderExcluirEntão... Eu estou precisando fazer o upload de um arquivo .sql, e gostaria de fazê-lo através de um formulário HTML.
Através deste formulário, o usuário encontraria o arquivo .sql a ser carregado, e os comandos PHP necessários executariam a tarefa.
Você saberia e poderia me dizer como fazer isso? Caso negativo, poderia me indicar uma bibliografia a respeito?
Obrigado!
Olá,, muito bom o post foi muito útil pra mim,, vc só precisa corrigir um erro na linha 24 substitua
ResponderExcluir$res = mysql_list_tables($dbname) or die(mysql_error());
por
$res = mysql_query("SHOW TABLES FROM $dbname") or die(mysql_error());
aí não vai ter mais erro ... valeww
Legal, comigo funcionou como eu fiz lá, talvez seja algum conflito de versão, obrigado por compartilhar, se alguém tiver problemas a solução está aqui.
ExcluirMe ajudou muito!
ResponderExcluirMuito obrigado \o/
Que bom! Obrigado pelo feedback.
ExcluirBoa noite.
ResponderExcluirO arquivo veio em branco. Sabe dizer o que pode ter acontecido?
Obrigado pelo post, e agradeço se poder responder minha pergunta.
Oi Amaury, o código além de retornar o arquivo no final ele grava um arquivo "temporario" com a extensão SQL e com o nome do banco de dados dentro da pasta onde o arquivo PHP de backup está.
ExcluirEste arquivo existe na sua aplicação? ele está preenchido?
Se ele não existir verifique as permissões de escrita de arquivo na sua pasta.
Se ele existir e estiver vazio, tente apaga-lo manualmente e rodar o processo novamente.
$res = mysql_list_tables($dbname) or die(mysql_error());
Excluirpor
$res = mysql_query("SHOW TABLES FROM $dbname") or die(mysql_error());
Provavelmente o seu problema é o que citaram a cima, da versao do seu php. ou da hospedagem. Experimente substituir a linha conforme citado.
Excelente post! muito obrigado por nos compartilhar seu conhecimento.
ResponderExcluirMuito bom usei e esta funcionando beleza
ResponderExcluirValeu obrigado
Salvou minha vida!!!
ResponderExcluirTenho nem o que dizer, senão, OBRIGADO!!
Funcionou direitinho..
ResponderExcluirMas tive q fazer a modificação que haseo comentou.
Este comentário foi removido pelo autor.
ResponderExcluirNao gerou o download no meu, pode me ajudar??
ResponderExcluirMas ele gerou o arquivo na pasta?
ExcluirUse o comando ini_set("display_errors", 1);
Logo no começo assim se der erro o php vai mostrar no browser e vc vai descobrir em que parte deu errado.
Aqui nos comentarios tem um caminho colocado pelo haseo q patece ter ajudado alguns.
Este comentário foi removido pelo autor.
ResponderExcluirOpaaa... Marcos, muito bom o post... pena que no meu deu um erro nas 17 primeiras linhas do arquivo gerado.
ResponderExcluirO resto está corretíssimo.
Se você puder me ajudar, por favor mandar um e-mail p/ mim eu respondo com o arquivo gerado.
Grande abraço.
Alex Alves de Almeida
alexalvesdealmeida@gmail.com
Marcos boa tarde, estou usando o seu script para teste no meu sistema, porem roda perfeitamente no servidor local porem não no servidor Web as versoes do phpmyadmin são respectivamente 5.5.27 e 5.0.33
ResponderExcluirfuncionou perfeitamente. a partir daqui posso enviar por email, registrar num banco de dados, etc
ResponderExcluir