Backup Database MySQL in PHP
In questo tutorial costruiremo un semplice script che esegue il backup di un database .
|
Lo script PHP consiste in un unico file molto corto (107 righe) facilmente configurabile impostando alcuni parametri da GET, in modo da poter rapidamente impostare se si vuole solo la struttura del database, struttura e dati eccetera. Una volta eseguito lo script, esso restituirà al browser un file. |
Vediamo per prima cosa la testa dello script che contiene tutte le costanti che vi consentiranno di comandare l'applicazione.
set_time_limit(0); // Rimuove limiti di tempo per l'esecuzione dello script corrente
error_reporting(E_ALL); // Dice a PHP di segnalare tutti gli errori in cui incorre
define('DB_SERVER', 'localhost'); // Host dove risiede il database MySQL
define('DB_USER', 'root'); // Nome utente db
define('DB_PASS', 'mypass'); // Password db
define('DB_NAME', 'test'); // Database di cui effettuare il backup
define('DB_FILE', 'dump_' . date("d_m_Y__\hH_\mi", time()) . '.sql'); // Nome del dump
define('DB_DROP', $_GET['drop'] == '1');
define('DB_IGNORE', $_GET['ignore'] == '1');
define('DB_DATA', $_GET['data'] == '1');
define('DB_STRUCTURE', $_GET['struc'] == '1');
define('INSERT_QUERIES', 100);
Diamo un'occhiata alle cinque costanti soprastanti che non ho commentato:
- - Aggiunge il comando MySQL "DROP TABLE IF EXISTS"
che elimina la tabella specificata se esistente. Utile prima di un "CREATE TABLE" della
medesima tabella.
Per attivarlo impostate drop a 1 via GET come nell'esempio che segue:
http://localhost/dumpetor.php?drop=1 - - Aggiunge il comando MySQL "IGNORE"
al comando "INSERT INTO", consentendo di continuare l'esecuzione del codice
SQL anche nel caso in cui si violasse l'univocità di una chiave.
Quindi, se ad esempio provate ad inserire due volte un record con lo stesso ID, che poniamo sia la chiave primaria della tabella, il secondo inserimento verrà semplicemente ignorato in quanto il valore risulta già presente.
http://localhost/dumpetor.php?ignore=1 - - Dice allo script che desideriamo eseguire il backup dei dati
(INSERT ...)
http://localhost/dumpetor.php?data=1 - - Dice allo script che desideriamo eseguire il backup della
struttura del database (CREATE TABLE ...)
http://localhost/dumpetor.php?struc=1 - - Imposta il numero di record massimo che ogni query INSERT può contenere (default = 100)
|
In base a quanto riportato pocanzi, l'url per eseguire il backup completo del database sarà il seguente:
Lo script prosegue con una condizione che termina lo script nel caso in cui non venga impostato alcun parametro e continua collegandosi al database mediante la classica mysql_connect(). |
if (!DB_DROP && !DB_IGNORE && !DB_DATA && !DB_STRUCTURE) exit;
$db = mysql_connect(DB_SERVER, DB_USER, DB_PASS) or die('Errore MySQL: ' . mysql_error() . ' (' . mysql_errno() . ')');
mysql_select_db(DB_NAME);
Continuiamo il tutorial introducendo la funzione datadump($table) che fornirà le query INSERT con tutti i dati della tabella specificata.
Questa funzione si servirà a sua volta di due query: una SELECT * per il prelievo di tutti i dati ed una SHOW COLUMNS usata per leggere il nome dei campi ma soprattutto se accettano come valore predefinito il valore speciale NULL.
function datadump($table)
{
global $db;
$dump = @mysql_query("SELECT * FROM `$table`;", $db);
if (@mysql_num_rows($dump) <= 0) // Se la tabella è vuota restituisce una stringa vuota
return '';
$result = "";
$insert_fields = "";
$stack = array();
$colonne = @mysql_query("SHOW COLUMNS FROM `$table`;");
$cols = array();
while ($col = @mysql_fetch_object($colonne))
{
$cols[$col->Field] = $col->Null; // Carica in un'array associativo il nome dei campi con il NULL si/no
$insert_fields .= "`" . $col->Field . "`, ";
}
$insert_fields = substr($insert_fields, 0, -2);
while ($d = @mysql_fetch_assoc($dump)) // Carica la tabella in un'array
$stack[] = $d;
foreach ($stack as $i => $val)
{
if (!($i % INSERT_QUERIES)) // Controlla se è stato raggiunto il limite di record per creare una nuova INSERT
{
if (strlen($result))
$result = substr($result, 0, -2) . ";\n";
$result .= "INSERT " . ((DB_IGNORE) ? 'IGNORE ' : '') . "INTO `$table` ($insert_fields) VALUES ";
}
$result .= "(";
foreach ($val as $key => $value)
{
if ($value == NULL) // Se il campo è vuoto controlla l'array $cols per assegnare il giusto valore predefinito
{
if ($cols[$key] == "YES")
$result .= 'NULL, ';
else $result .= "'', ";
}
else $result .= "'" . mysql_real_escape_string($value, $db) . "', ";
}
$result = substr($result, 0, -2) . "), ";
}
return substr($result, 0, -2) . ";\n";
}
Ora vediamo la parte finale dello script.
Con due chiamate a header() impostiamo il contenuto dell'output introducendo al browser che si tratta
di un file che prenderà il nome dalla costante DB_FILE:
header("Content-type: application/octet-stream");
header("Content-Disposition: attachment; filename = " . DB_FILE);
$query = "SHOW TABLE STATUS FROM `" . DB_NAME . "`;"; // Legge la lista completa delle tabelle dal DB specificato
$tabelle = @mysql_query($query, $db);
echo 'SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";' . "\n\n"; // Imposta il comportamento per la direttiva AUTO_INCREMENT
while ($tab = @mysql_fetch_object($tabelle))
{
if (DB_STRUCTURE) // Se viene richiesta la struttura delle tabelle ...
{
if (DB_DROP) // Se viene impostato il drop via GET
echo "DROP TABLE IF EXISTS " . $tab->Name . ";\n";
$query = "SHOW CREATE TABLE `" . $tab->Name . "`;";
$create = @mysql_query($query, $db);
$create = @mysql_fetch_assoc($create);
echo $create["Create Table"] . ";\n\n"; // Stampa il CREATE TABLE generato da MySQL
}
if (DB_DATA) // Se vengono richiesti i dati ...
echo datadump($tab->Name) . "\n\n";
}
E con questo pezzo di codice abbiamo finito il tutorial.
Potete scaricare lo script allegato pronto a funzionare con un colpo di FTP.
Se riscontrate anomalie o avete suggerimenti per migliorare lo script scrivete un commento.
Buon lavoro.
| Allegato | Dimensione |
|---|---|
| dumpetor.zip | 1.16 KB |


Commenti
Problemi con header
Salve volevo dirti che lo script è fantastico, ma se io volessi salvare il file sempre in una cartella senza selezionarla come posso farlo?
header
togli gli header e metti tutto in una variabile invece di fare sempre echo e a fine script scrivi il file, se vuoi usa file_put_contents()
ripristino
Ciao, grazie per l'articolo.
Ti volevo chiedere una volta ottenuta la copia di backup come faccio poi, in caso di problemi, a ripristinare la medesima copia?
Grazie.
backup
il backup che ritrovi non è altro che codice SQL, quindi puoi eseguirlo da phpMyAdmin o da console mysql.
forum
Se necessitate di aiuto usate il forum apposito:
http://www.realizzazione-sito.info/forum/
ciao ho il parametro safe
ciao ho il parametro safe mode di apache attivato e mi da errore in questo senso, come posso modificare il codice senza togliere il safe mode?
grazie.
dimenticavo ... se commenti
dimenticavo ... se commenti le due header() ti dovrebbe uscire il dump direttamente senza farti scaricare il .sql, quindi copia il sorgente html e salvatelo in un .sql tuo.
prova a commentare le due
prova a commentare le due header() in testa.
il safe mode cmq è deprecato, ti consiglio di aggiornare il tuo ambiente.