Fare il backup compresso del database MySQL con PHP e inviarlo come allegato email




Ero un felice utente di MySQLDumper fino a quando Tophost non ha aggiornato i server all’architettura cloud e all’ultima versione di PHP, cosa che ha comportato la scomparsa di un paio di moduli PERL necessari e mi ha lasciato a terra (la routine PHP di MySQLDumper è molto lenta ed usa javascript per ricaricare le pagine, il che la rende incompatibile sia con wget che cronjob remoti come SetCronJob.com).

Così ho cercato e trovato due guide su internet (questa, e questa), le ho mischiate assieme potenziando soprattutto il codice di David Walsh, ho aggiunto un pizzico di compressione bzip2, e ho messo il tutto sul mio spazio web.

Ho rimosso la parte in cui è possibile selezionare quali tabelle salvare: ho pensato che un backup degno di questo nome è “all-inclusive”, e in fondo chiunque avesse il bisogno particolare di salvare solo alcune tabelle dovrebbe essere anche piuttosto navigato da poter modificare il codice in proprio.

AGGIORNAMENTO 9/9/11: siccome ne avevo bisogno (lo script andava incontro ad un errore di memoria insufficiente) ho aggiunto qualche riga per riattivare la lista delle tabelle da ignorare, basta riempire l’array con i nomi che vi servono.

Questo è il risultato:

<?php
$creationstart=strtok(microtime()," ")+strtok(" ");

$dbhost="indirizzo.server.mysql";
$dbname="nomedatabase";
$dbuser="usernamemysql";
$dbpass="passwordmysql";

$mailto="scrivimi@lamiacasella.it";
$subject="Backup DB";
$from_name="Il tuo caro sito web";
$from_mail="noreply@ilmiosito.it";

mysql_connect($dbhost, $dbuser, $dbpass);
mysql_select_db($dbname);

$tablesblocklist=array(
    "tablename1"=>1,
    "tablename2"=>1,
    "tablename3"=>1,
);
$tables = array();
$result = mysql_query("SHOW TABLES");
while($row = mysql_fetch_row($result))
$tables[] = $row[0];
foreach($tables as $table) {
if (!isset($tablesblocklist[$table])) {
$result = mysql_query("SELECT * FROM $table");
$return.= "DROP TABLE IF EXISTS $table;";
$row2 = mysql_fetch_row(mysql_query("SHOW CREATE TABLE $table"));
$return.= "\n\n".$row2[1].";\n\n";
while($row = mysql_fetch_row($result)) {
$return.= "INSERT INTO $table VALUES(";
$fields=array();
foreach ($row as $field)
$fields[]="'".mysql_real_escape_string($field)."'";
$return.= implode(",",$fields).");\n";
}
$return.="\n\n\n";
}
}
$filename='db-backup-'.date("Y-m-d H.m.i").'.sql.bz2';

$content=chunk_split(base64_encode(bzcompress($return,9)));
$uid=md5(uniqid(time()));
$header=
"From: ".$from_name." <".$from_mail.">\r\n".
"Reply-To: ".$replyto."\r\n".
"MIME-Version: 1.0\r\n".
"Content-Type: multipart/mixed; boundary=\"".$uid."\"\r\n\r\n".
"This is a multi-part message in MIME format.\r\n".
"--".$uid."\r\n".
"Content-type:text/plain; charset=iso-8859-1\r\n".
"Content-Transfer-Encoding: 7bit\r\n\r\n".
$message."\r\n\r\n".
"--".$uid."\r\n".
"Content-Type: application/octet-stream; name=\"".$filename."\"\r\n".
"Content-Transfer-Encoding: base64\r\n".
"Content-Disposition: attachment; filename=\"".$filename."\"\r\n\r\n".
$content."\r\n\r\n".
"--".$uid."--";
mail($mailto,$subject,"",$header);

$creationend=strtok(microtime()," ")+strtok(" ");
$creationtime=number_format($creationend-$creationstart,4);
echo "Backup del database completato, compresso a bz2 e spedito per posta elettronica in $creationtime secondi";
?>

(WordPress ha rimosso l’indent e non ho voglia di aggiustarlo a mano)

L’intera routine viene completata in circa 7secondi sul mio non tanto sveglio server Tophost, inclusi la compressione bzip2 e l’invio per posta elettronica, mentre il salvataggio del file in formato solo testo nel codice originale di David impiegava sullo stesso server 17secondi; probabilmente la differenza è dovuta alla rimozione di diversi cicli ridondanti, e all’uso delle funzioni native mysql_real_escape_string() e implode().

Sinceri ringraziamenti vanno ai rispettivi autori delle guide, senza le quali non stare scrivendo questa paginetta oggi 😉




4 commenti su “Fare il backup compresso del database MySQL con PHP e inviarlo come allegato email”

  1. Many thanks! Too bad I had to read through all the comments on David’s tutorial to figure out what wasn’t great about his script before finding your post, instead of your post showing up first in Google results. This is much easier for me to understand than David’s tutorial was, and seems to work awesome so far!

  2. Hi,

    for database backups I use bash scripts, for example:


    #!/bin/sh

    DBUSER=""
    DBHOST="localhost"
    DBPASS=""
    BACKUPDIR="/home/user/dir"

    DBS=`mysql -u$DBUSER -h$DBHOST -p$DBPASS -e"show databases"`
    WEEKDAY=`date +%A`

    for DATABASE in dbnameone dbnametwo
    do

    FILENAME=$DATABASE-$WEEKDAY.sql
    mysqldump -u$DBUSER -h$DBHOST -p$DBPASS $DATABASE > $BACKUPDIR/$FILENAME

    done

    I wrote on my blog a backup tutorial where rsync is used for the file transport.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *