2010-07-27 6 views
7

J'utilise le script Database Backup de David Walsh (http://davidwalsh.name/backup-mysql-database-php) pour sauvegarder ma base de données MYSQL en tant que fichier .sql sur mon serveur.Pourquoi mon script de sauvegarde de base de données ne fonctionne-t-il pas en PHP?

J'ai créé un utilisateur nommé backup et lui ai donné tous les privilèges (juste pour être sûr). Ensuite, j'ai mis le code dans un fichier php et configurer un travail cron pour exécuter le fichier php.

Voici le code:

/* backup the db OR just a table */ 
function backup_tables($host,$user,$pass,$name,$tables = '*') 
{ 

    $link = mysql_connect($host,$user,$pass); 
    mysql_select_db($name,$link); 

    //get all of the tables 
    if($tables == '*') 
    { 
     $tables = array(); 
     $result = mysql_query('SHOW TABLES'); 
     while($row = mysql_fetch_row($result)) 
     { 
      $tables[] = $row[0]; 
     } 
    } 
    else 
    { 
     $tables = is_array($tables) ? $tables : explode(',',$tables); 
    } 

    //cycle through 
    foreach($tables as $table) 
    { 
     $result = mysql_query('SELECT * FROM '.$table); 
     $num_fields = mysql_num_fields($result); 

     $return.= 'DROP TABLE '.$table.';'; 
     $row2 = mysql_fetch_row(mysql_query('SHOW CREATE TABLE '.$table)); 
     $return.= "\n\n".$row2[1].";\n\n"; 

     for ($i = 0; $i < $num_fields; $i++) 
     { 
      while($row = mysql_fetch_row($result)) 
      { 
       $return.= 'INSERT INTO '.$table.' VALUES('; 
       for($j=0; $j<$num_fields; $j++) 
       { 
        $row[$j] = addslashes($row[$j]); 
        $row[$j] = ereg_replace("\n","\\n",$row[$j]); 
        if (isset($row[$j])) { $return.= '"'.$row[$j].'"' ; } else { $return.= '""'; } 
        if ($j<($num_fields-1)) { $return.= ','; } 
       } 
       $return.= ");\n"; 
      } 
     } 
     $return.="\n\n\n"; 
    } 

    //save file 
    $handle = fopen('../backup/db-backup-'.time().'-'.(md5(implode(',',$tables))).'.sql','w+'); 
    fwrite($handle,$return); 
    fclose($handle); 
} 

backup_tables('localhost','alupto_backup','pass','*'); 

Lorsque la tâche cron exécute, la sauvegarde ne fonctionne pas et je reçois un e-mail avec l'erreur qui apparaît:


Avertissement: mysql_fetch_row(): argument fourni n'est pas une ressource de résultat MySQL valide dans /home5/ideapale/public_html/amator ders_basic/admin/backup.php en ligne

Sur la ligne 18 est ce code:

while($row = mysql_fetch_row($result))

Quand je lance le SQL (SHOW TABLES) dans phpMyAdmin, cela fonctionne très bien et me montre une liste de toutes les tables. Mais pour une raison quelconque, je reçois une erreur lorsque le fichier php essaie d'exécuter le SQL.

Pourquoi mon script de sauvegarde de base de données ne fonctionne-t-il pas?

Répondre

14

Cela ne fonctionnera pas pour sauvegarder votre base de données en tant que script SQL, à moins que votre base de données ne soit qu'une base de données de jeu, l'équivalent d'un script "hello world".

Ce script est effroyable. Vous ne devez pas l'utiliser pour sauvegarder une base de données. Ce script a été écrit avant: PHP Database Dump Script - are there any issues?

  • Aucune erreur après vérification mysql_connect() ou mysql_queries(). Vous avez probablement juste donné un mauvais mot de passe ou quelque chose, mais vous ne le sauriez jamais parce que le script ne vérifie pas que la connexion a réussi.

  • Il ne produira pas la déclaration droite INSERT si votre base de données contient des valeurs NULL.

  • Les jeux de caractères ne sont pas gérés.

  • addslashes() est not suitable pour échapper données.

  • Les noms de tables ne sont pas délimitées.

  • ne sauvegarde pas vues, des procédures, des fonctions ou déclencheurs. Mysql_query() met en tampon les résultats, donc si vous avez une table avec des milliers de lignes ou plus, vous dépasserez votre limite de mémoire PHP. En fait, le script concatène la série d'instructions INSERT dans une seule variable PHP. Donc, avant qu'il ne finisse, vous aurez votre entière base de données représenté en mémoire.

Personne ne devrait jamais utiliser ce script. C'est une poubelle totale, et je ne dis pas ça à la légère.

utiliser Juste pour exécuter mysqldump ShellExec().

@ Álvaro G. Vicario a un bon point, vous n'avez même pas besoin d'utiliser PHP pour cette tâche. Je supposais que vous devez faire une sauvegarde à partir d'un script PHP. Voici comment je créerais une sauvegarde à partir d'un script cron:

Créer un script shell, on peut l'appeler ce que vous voulez, par exemple mymysqldump.sh. Voici comment j'écrire:

: 
: ${BACKUP_HOST:="localhost"} 
: ${BACKUP_DATABASE:="mydatabase"} 
: ${BACKUP_DIR:="/opt/local/var/db/mysql5/backups"} 
: ${BACKUP_FILE:="${DATABASE}-`date +%Y%m%d%H%M%S`"} 

mysqldump -h ${BACKUP_HOST} ${BACKUP_DATABASE} > ${BACKUP_DIR}/${BACKUP_FILE} 

Bien sûr personnaliser les valeurs des variables selon les besoins de votre environnement.

Vous pouvez remarquer que le nom d'utilisateur et le mot de passe sont et non dans ce fichier. S'il vous plaît ne pas mettre des mots de passe dans les scripts en texte brut afin que tout le monde puisse les lire. Au lieu de cela, nous les placerons dans un fichier d'options pour le rendre plus sûr.

Créez un utilisateur de système d'exploitation spécial qui exécutera la sauvegarde à partir de cron. Votre système peut avoir un utilisateur spécial "mysql" ou "_mysql" pour exécuter le serveur MySQL, mais cet utilisateur peut être configuré pour n'avoir aucun répertoire personnel valide. Vous avez besoin d'un utilisateur disposant d'un répertoire personnel. Appelons-le "mybackup".

Sous le répertoire de cet utilisateur, créez un fichier .my.cnf avec le contenu suivant:

[mysqldump] 
user = alupto_backup 
password = xyzzy 

Où « alupto_backup » et « xyzzy » sont le nom d'utilisateur MySQL et son mot de passe (les modifier pour votre environnement). Définissez la propriété et le mode de ce fichier de sorte que seul son propriétaire peut lire:

chown mybackup .my.cnf 
chmod 600 .my.cnf 

Créer un répertoire bin sous la maison de cet utilisateur et de mettre notre script shell en elle.

mkdir ~mybackup/bin 
mv mymysqldump ~mybackup/bin 

Maintenant, vous pouvez exécuter le script shell pour le tester:

sh ~mybackup/bin/mymysqldump 

Maintenant, créez un fichier cron pour cet utilisateur:

crontab -u mybackup 

@daily ~mybackup/bin/mymysqldump 

Cela devrait suffire.

+0

Et il utilise le 'ereg_replace()' déprécié juste pour ajouter à la liste. –

+1

shellexec? Pourquoi même utiliser PHP pour exécuter un programme via cron? –

+0

Ok, je n'ai jamais réalisé ça. Connaissez-vous un bon tutoriel qui montre comment utiliser shellexec() pour lancer mysqldump? – zeckdude

0

Utilisez la fonction mysql_error() pour voir de quoi MySQL se plaint.

+0

Où pourrais-je ajouter cela? – zeckdude

0

Vous devez vous assurer que mysql_query ne renvoie pas d'origine un flux non-stream. Essayez ceci:

.... 

if (false !== ($result = mysql_query('SHOW TALBES')) { 
    while($row = mysql_fetch_row($result)) 
    { 
     $tables[] = $row[0]; 
    } 
} else { 
    // see Mchl's point about mysql_error 
} 
+0

Qu'est-ce que j'écrirais dans la clause else? – zeckdude

+0

Un simple 'echo mysql_error()' serait un bon début. C'est juste pour dire ce qui ne va pas avec la requête. Toute déclaration de débogage suffirait, cependant. – efritz

3

Le script semble très faible IMHO. Vous devriez envisager d'utiliser mysqldump il est disponible dans votre système.

Mise à jour

La ligne de commande de base serait:

mysqldump -hYOURHOSTNAME -uYOURUSER -pYOURPASSWORD infocap > dump.sql 

Vous pouvez tester mysqldump dans votre ordinateur local et, une fois que vous êtes satisfait des résultats, soit créer un script shell ou ajouter directement comme une tâche cron.

+0

Cela ressemble à une bonne option. Connaissez-vous un bon tutoriel qui montre comment faire cela? La documentation MYSQL n'est pas facile à comprendre. – zeckdude

+0

@zeckdude: Voir la mise à jour –

Questions connexes