picture picture
juin 12, 2005 MySQL, PHP 57 Commentaires

Script PHP de sauvegarde automatique des bases de données

… avec auto-effacement des sauvegardes de plus de 7 jours love

Ce script me permet une sauvegarde quotidienne de mes bases directement sur le FTP.
Un fichier .sql est créé et stocké automatiquement tous les soirs, auto-effaçable au bout d’une semaine.
Je complète ce dispositif par une sauvegarde hebdomadaire de l’ensemble des fichiers du serveur: rien n’est trop sà»r pour ces petites choses, un plantage de serveur ou un hack sont si vite arrivés … :C

Le script :

<?php
// création d’une fonction comportant les identifiants de connexion au FTP :

function mysql_structure() {
$host = ‘mon_serveur’;
$user = ‘mon_login’;
$pass = ‘mot_de_passe’;
$base = ‘nom_de_la_base’;

// création d’un fichier affichant en boucle le contenu des tuples de la base :

mysql_connect($host, $user, $pass);
mysql_select_db($base);
$tables = mysql_list_tables($base);
while ($donnees = mysql_fetch_array($tables))
{
$table = $donnees[0];
$res = mysql_query("SHOW CREATE TABLE $table");
if ($res)
{
$insertions = "";
$tableau = mysql_fetch_array($res);
$tableau[1] .= ";";
$dumpsql[] = str_replace(" ", "", $tableau[1]);
$req_table = mysql_query("SELECT * FROM $table");
$nbr_champs = mysql_num_fields($req_table);
while ($ligne = mysql_fetch_array($req_table))
{
$insertions .= "INSERT INTO $table VALUES(";
for ($i=0; $i<=$nbr_champs-1; $i++)
{
$insertions .= "’" . mysql_real_escape_string($ligne[$i]) . "’, ";
}
$insertions = substr($insertions, 0, -2);
$insertions .= "); ";
}
if ($insertions != "")
{
$dumpsql[] = $insertions;
}
}
}
return implode("
", $dumpsql);
}

// creation d’une fonction file_put_content si le script est en PHP4 :

if(!function_exists(‘file_put_contents’)) {
function file_put_contents($filename, $data, $file_append = false) {
$fp = fopen($filename, (!$file_append ? ‘w+’ : ‘a+’));
if(!$fp) {
trigger_error(‘file_put_contents ne peut pas écrire dans le fichier.’, E_USER_ERROR);
return;
}
fputs($fp, $data);
fclose($fp);
}
}

// création du fichier de dump sur le même niveau que ce fichier dump.php

file_put_contents("sqldump_".date("d-n-Y").".sql", mysql_structure());

// effacement du fichier precedant (créé 7 jours plus tot)
$time_old = getdate(mktime()-(7*24*3600));
$an = $time_old[‘year’];
$mois = $time_old[‘mon’];
$jour = $time_old[‘mday’];

// formatage des jours à 1 chiffre

for($k=1; $k<10; $k++)
{
if ($jour==$k)
{
$jour=’0′.$jour;
}
}

$date_old=$jour.’-‘.$mois.’-‘.$an;
$file_old="sqldump_".$date_old.".sql";
unlink($file_old);
?>

Derniere étape : utilisation des services gratuits de WEBCRON pour lancer ce script tous les jours.

Ce site génial (et gratuit) vous permet de déclancher à distance, et à heures fixes, votre fichier dump.php …

Mode d’emploi très intuitif, vous commencez par créer un compte qui vous permettra de lancer 6 scripts pour 6 bases des données MySQL (si vous en avez plus… creez plusieurs comptes !)

Pour lancer, par exemple, tous les soirs à 20h un fichier dump.php stocké dans un dossier « dump », vous aurez ceci :

et encore dans l’interface « mes tâches » :

Vous aurez donc « in fine » dans le dossier « dump » : 7 fichiers de sauvegarde (les 7 derniers jours) + le fichier de script :

Génial, non ?! :))

57 Responses to “Script PHP de sauvegarde automatique des bases de données”

57 Commentaires

  1. armand boutchouang dit :

    c’est un diamant que je viens trouver pourais-je l’adapter à cake php???

  2. webtolosa dit :

    Difficile de faire du PHP sans connaitre le code, fati… L’adaptation est pourtant simple.

  3. fati dit :

    bonjour merci pour ce script ;mais ca il sauvegarde tout la base dans un seul fichier .sql; svp je cherche un script qui sauvegardée chaque table de la base de donnes dans un fichier différent de l’autre et avec son nom si possible bien sur merci d’avance

  4. webtolosa dit :

    Vous avez un petit tuto sur les envois de pièces jointes aux e-mails ici > http://www.webtolosa.com/2010/02/10/envoyer-une-piece-jointe-a-un-mail-en-php/

  5. noftal dit :

    Très intéressant. Savez-vous comment compléter ce tuto pour que le fichier .sql soit automatiquement sauvegardé sur votre disque dur (soit directement, soit par l’intermédiaire de l’envoi d’un mail automatique à votre attention contenant en PJ le fichier .sql) ?

  6. webtolosa dit :

    Bonjour passap
    ne fait pas de copier-coller, souvent les quotes ou apostrophes ne sont pas ascii : remplace manuellement toutes les quotes, puisque tu as une erreur sur la première paire.
    Je ne connais pas l’hôte de Free, peut-être, il me semble que c’est :
    $host = ‘sql.free.fr’;
    Cdt

  7. Transloc610 dit :

    Bonjour

    j’ai copié collé le script

    host j’ai mis : free.fr ou ‘free.fr’ ou ‘passaps.free.fr’ ou ‘sql.free.fr’
    a chaque fois j’ai :
    Parse error: syntax error, unexpected T_STRING in /mnt/171/sdb/d/a/passaps/dump/dump.php on line 54

    ou fais-je une erreur

    je lance
    http://passaps.free.fr/dump/dump.php

    Mercid e votre aide

  8. lumycaan dit :

    Non, je suis chez LWS (serveur dédié)

  9. webtolosa dit :

    tu es chez OVH ? Free ? ces 2 hébergeurs, pour les mutualisés, n’aiment pas trop qu’on bidouille les paramètres…

  10. lumycaan dit :

    Bonjour,

    J’ai utilisé la 3ème méthode pour augmenter la taille de la mémoire au niveau du serveur en incluant le code ci-dessous dans mon script.

    ini_set(‘memory_limit’,’128M’);

    Le problème c’est que j’ai toujours le même message d’erreur.

    Help!!!!!!

  11. lumycaan dit :

    Bonjour,

    Je viens d’essayer cette méthode:

    ini_set(‘memory_limit’,’128M’);

    Mais le résultat est le même. Toujours le message d’erreur.

  12. webtolosa dit :

    @lumycaan : il te faut augmenter la variable « memory_limit » de PHP sur ton serveur. Tu as toutes les solutions là par exemple : http://www.benjamin-agullana.fr/serveur/augmenter-php-memory_limit.html et tu mets ta limite à 128M

  13. lumycaan dit :

    Autre idée qui me vient à l’esprit. Ne pourrait-on pas modifier le code de façon à ce qu’il ne prenne pas l’intégralité de la base de données d’un coup. Je pourrais faire un 1er dump de mes tables 1 à 200 et un second dump de mes tables 201 à 400. Ce qui ferait que la taille de les sauvegardes serait divisé par 2. Et là, ça fonctionnerait comme avant. Par contre, je ne sais pas comment le faire.

  14. lumycaan dit :

    Bah le soucis c’est qu’elle va encore augmenter en taille car ce n’est que le début…
    Je fais déjà des « épurements » de données tous les jours en automatique.
    Je suis sur un serveur dédié mais je n’y connais rien à ce niveau là. Je ne sais donc pas comment accéder au php.ini.

    Si tu peux me l’expliquer, je suis preneur.

    Merci à toi de tes réponses.

  15. webtolosa dit :

    60 MO pour une base ça commence à faire lourd : tu ne peux pas commencer par l’alléger (créer un script qui supprime toutes les commandes, ou les clients, ou les posts …de plus de 3 ans par exemple ?)

    Sinon tu peux jouer sur ton php.ini en passant la taille des téléchagements à 128MO par exemple (soit directement sur le serveur si tu y a accès, soit avec un htacess par exemple): pas très safe en terme de sécurité, mais c’est la limite des scripts en PHP…

  16. lumycaan dit :

    Bonjour,

    Ce script fonctionnait très bien jusqu’à dernièrement. Mais depuis que ma base a dépassée 60Mo, j’ai le message d’erreur suivant:
    Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 54815698 bytes) in /var/www/clients…..

    Pouvez-vous m’aider?

    Je vous en remercie par avance.

  17. Mataro dit :

    J’ai cherché ce code depuis quelque jours, la me souri car je vais l’utiliser dans le bref delai et je vous fairai signe si ca bien marché. Be blessed

  18. webtolosa dit :

    regarde peut-être l’encodage ou le type de bases.
    J’ai quelqufois des soucis avec un transfert innoDB vers MyISAM, ou des soucis avec l’autoincrement

  19. IGH dit :

    Le script fonctionne et me crée un fichier .sql qui semble correct (visionné dans bbedit), mais si je veux recharger la bd à partir de ce fichier avec phpMyAdmin, j’ai une erreur « Missing parameters » (après un long moment), ce qui n’est pas le cas quand je crée un backup manuellement avec phpMyAdmin (la bd se recharge en quelques secondes).

    Une explication ?

  20. webtolosa dit :

    en espérant que ta base ne soit pas trop lourde, tu crées un cron directement sur le serveur c’est simple vois avec l’admin de ton serveur apache (je suppose)

  21. A-snowboard dit :

    Pas encore testé le script mais ça ne serait tarder.

    Par contre avoir une sauvegarde, c’est bien, mais l’avoir en dehors du serveur c’est mieux !

    Pas moyen d’avoir un envoi de mail de la base sur une adresse donnée ?

  22. chuck dit :

    Le script fonctionne, en revanche, le fichier généré n’est pas réutilisable tel quel pour restaurer une base de donnée.
    Il y a une erreur à cette ligne :

    $dumpsql[] = str_replace( » « , «  », $tableau[1]);

    qui retire les espaces entre les commandes.

    Version corrigé :
    $dumpsql[] = str_replace(«  »,  » « , $tableau[1]);

    L’autre souci est que les contraintes de clé étrangères ne sont pas mises en fin de code, ce qui rend impossible la création de certaines tables avant la création d’autres.

  23. Guillaume dit :

    Bonjour from Toulouse,

    J’ai installé ce script…qui fonctionne sur mon mutualisé OVH, sauf la fonction qui consiste à supprimer la sauvegarde plus vieille de 7j. Ai-je loupé quelque-chose ?

    Merci d’avance

  24. cocotte dit :

    j’ai trouvé!
    l’expédition de la sauvegarde par mail marche impec!
    :))
    ~:(
    il me reste plus qu’a tester CRON mais ça je sais que c’est fastoch’

    merci et encore bravo!!!

  25. webtolosa@Mc dit :

    en principe cela signifie que ton serveur 1&1 n’accepte pas une des fonctions ou une extension que tu y mets.
    Souvent il s’agit des fichiers .htaccess que les serveurs mutualisés n’acceptent pas tous donc si tu as mis un fichier .htaccess pour augmenter le temps d’exécution de ton script, enlève le et regarde si cela marche.

    Au passage, si je peux me permettre … 1&1 ce n’est vraiment pas top question hebergement. Contacte moi par e-mail (voir menu de gauche contact > webtolosa) si tu veux des tuyaux.

  26. Mc dit :

    Même problème sur 1and1 avec une erreur 500.
    Et je n’ai pas très bien compris la solution proposée plus haut :|

  27. Noliv dit :

    MAGNIFIQUE
    avec l’option zip à la fin que du bonheur
    thanks

  28. Webtolosa dit :

    effectivement ta base doit être trop un peu obèse…
    La seule solution (à moins de purger un peu la base du forum ;))est d’augmenter le temps d’exécution des scripts sur le serveur avec un htaccess de type "php_value max_execution_time 420" si ton hébergeur accepte… regarde ici il y a le mode d’emploi :http://www.webtolosa.com/index.p...

  29. Nico dit :

    Bonjour,

    Lorsque j’exécute le script, cela me retourne l’erreur suivante:

    Fatal error: Maximum execution time of 300 seconds exceeded in /home/httpd/vhosts/club205gti.fr/httpdocs/forum09/dump/dump.php on line 35

    Ma base doit être trop grosse…
    Auriez vous une solution??? (et même l’idéal serait de sauvegarder table par table…).
    Merci!!!
    ;)

  30. ReDiX dit :

    Regarde si tu as un .htaccess, si c’est le cas déplace ton script dans un dossier dans ce fichiers la

  31. Gégé dit :

    Pour info le serveur est en PHP 4.4.9.

  32. Gégé dit :

    Bonjour,

    J’ai recopié intégralement le script, l’ai sauvegardé après avoir indiqué les paramètres de connexion à la base. Je l’ai transféré sur mon mutualisé 1and1, puis je l’ai appelé dans le navigateur.

    J’obtiens l’erreur suivante (pas très explicite, j’en conviens) :
    Error 500 – Internal server error
    Un problème inattendu est survenu.
    Veuillez réessayer ultérieurement.

    Si quelqu’un avait une idée géniale …

  33. ed130 dit :

    Excellent script, j’ai simplement mis en commentaire la ligne ‘// unlink($file_old);
    ‘ afin d’éviter un retour erreur du serveur car j’utilise un hébergement mutualisé chez OVH et je crains un retour erreur du serveur. Pour info, leur interface de gestion Manager permet de programmer des taches cron à la fréquence que l’on souhaite. Je repasserai cette ligne en écriture dans 7 jours.

    Merci !

  34. Nico dit :

    :)) vraiment très pratique, et également merci pour l’astuce des caractères accentués !

  35. Xav dit :

    J’ai trouvé si ca peut aider d’autres personnes :

    Ajouter : mysql_query("SET NAMES UTF8");


    mysql_connect($host, $user, $pass);
    mysql_select_db($base);

    mysql_query("SET NAMES UTF8");

    $tables = mysql_list_tables($base);

  36. xav dit :

    Bravo pour ce script, par contre j’ai un petit souci avec les caractères accentués qui sont mal interprétés lors de l’export dans le fichier SQL. Est-ce que vous auriez une idée pour rétablir le bug ?!
    D’avance merci

  37. dav dit :

    :""( help :""(

  38. dav dit :

    j’ai essayé ce script avec succès, malheureusement mes tables dont les noms ne sont composées que de chiffres ne sont pas sauvegardées.
    après divers essais je me suis rendu compte que mon problème venait de la requête "SHOW CREATE TABLE $table" quoi échappe les noms composés de chiffres.
    quelqu’un voit-il une solution à mon problème?
    merci pour vos réponses

    ps: encore bravo pour ce script :bravo:

  39. max dit :

    Excellent !!!
    Fonctionne impeccablement pour plusieurs bdd en même temps…
    MERCI BEAUCOUP !
    :))

  40. weshcoast dit :

    Bonjour en executant ce script j’obtient l’erreur :

    Fatal error: Maximum execution time of 6 seconds exceeded in /www/weshcoast/forum/dmp/dump.php on line 35

    cette ligne correspond a :

    }
    $insertions = substr($insertions, 0, -2);
    $insertions .= "); ";

    Il s’agit surement du erreur due au temsp d’execution mais je suis chez olympe network je ne sais pas comment le réglé ( htaccess n’a pas fonctionné ) …

    Ceci est assez urgent , merci de votre aide

  41. webtolosa dit :

    @JO

    difficile de te donner un exemple, il faut que tu aies les paramètres de connexion à TA base (ton hébergeur a dû te les donner)
    Si tu veux un exemple bidon, ça donne un truc du genre :
    $host = ‘108.92.45.85’;
    $user = ‘toto’;
    $pass = ‘1234’;
    $base = ‘login_db’;

  42. JO dit :

    Je n’arrive pas à me connacter à ma base :

    Peux-tu donner un exemple de valeurs stp
    $host = ‘mon_serveur’;
    $user = ‘mon_login’;
    $pass = ‘mot_de_passe’;
    $base = ‘nom_de_la_base’;

  43. jean dit :

    merci. ça marche très bien.

  44. webtolosa dit :

    non, pas vraiment…
    Mais il faut que tu installes et utilises par exemple la librairie zip.lib.php :
    http://www.phpfrance.com/tutoria...

    Ensuite tu n’as qu’à récupérer le fichier truc.sql que tu as déposé sur ton serveur, tu le zippes (regardes le lien ci-dessus), et tu l’envoies avec une bête fonction mail()
    Tout doit tenir sur le même fichier cron :)

    Tu as même un autre exemple de zip ici

  45. Jean dit :

    bonjour,

    merci pour ce super script et la bonne idée d’utiliser webcron.

    Est ce que cela serait compliqué de transmettre automatiquement le fichier gzipé par mail ? (ma base est petite donc ça serait pas mal dans ma situation).

  46. @webjo dit :

    Desolé de decouvrir tard ton post … si tu repassais il est bien évidemment possible de mettre 4 crons … soit 4 fichiers éxécutables PHP (un par base) et 4 cons pour les lancer !

    Tu peux aussi mettre le même code 4 fois de suite sur un seul fichier, ça se lancera en suite => bref pas de problème :)

  47. Adnane dit :

    :)) :)) :)) :)) :)) :)) :)) :bravo: :bravo: :bravo: :bravo:

  48. webjo dit :

    Bonjour,

    Je suis chez 1&1 et j’ai 4 BD à sauvegarder est ce que cela est possible avec votre script ? Merci

    Cordialement

  49. Oxydoreduction dit :

    Génial merci :bravo:
    Par contre je suis passé par le web cron de Saint Pitoune la Creuviere parceque j’avais besoin d’une fréquence de lancement plus élevée qu’un par jour. Là, j’ai programmé mon script 2 fois par jour nickel.

  50. webtolosa dit :

    bien vu et merci de ton partage :)

  51. sikko dit :

    merci pour ton script qui fonctionne très bien.
    J’ai pour ma part ajouté un petit bout de code qui permet de gzipper le tout, et de supprimer le fichier .sql:

    /******************************************
    * COMPRESSION D’UN FICHIER DU SERVEUR
    *
    * – lecture des données originales
    * – compression avec gzencode()
    * – écriture des données compressées
    * – affichage du gain de la compression
    *
    * 29 mai 2003, Hugo ETIEVANT
    * http://cyberzoide.developpez.com/php4/
    *******************************************/

    // nom et chemin du fichier à compresser
    $filename = "sqldump_".date("d-n-Y").".sql";

    // ouverture du fichier à compresser
    if($fp = fopen($filename, "rb")) {

    // lecture du contenu
    $size1 = filesize($filename);
    $data = fread($fp, $size1);
    // fermeture
    fclose($fp);

    // compression des données
    $gzdata = gzencode($data, 9);

    // ouverture et création du fichier compressé
    if($fp = fopen($filename.’.gz’, ‘wb’)) {

    // écriture des données compressées
    fwrite($fp, $gzdata);
    // fermeture
    fclose($fp);

    // calcul gain de la compression
    $size2 = filesize($filename.’.gz’);
    $diff = $size1-$size2;
    $pc = round($diff/$size1*100, 2);
    echo "Gain de la compression : $diff octets soit $pc %.";
    $fichier_a_supp = "sqldump_".date("d-n-Y").".sql";
    unlink($fichier_a_supp);
    } else {
    echo "Impossible d’ouvrir $filename.gz en écriture.";
    }

    } else {
    echo "Impossible d’ouvrir $filename en lecture.";
    }

  52. webtolosa dit :

    Bonjour prach, comme il est dit dans le script, la fonction file_pu_contents() est une fonction PHP5. Vérifie la version PHP de ton serveur avec un phpinfo() Donc si le fichier du script est hébergé sur un serveur qui roule sur PHP4, il te faut « créer » cette fonction, et tu as le code ci-dessus, regarde la partie commentée « // creation d’une fonction file_put_content si le script est en PHP4 : »

  53. Prach dit :

    bonjour, j’ai un message d’erreur lorsque j’exécute ce script :
    Call to undefined function: file_put_contents()

    que faut il modifier ? :|

  54. webtolosa dit :

    c’est normal mixo : ce message te dit que tu ne peux pas effacer les sauvegardes des jours précédents… parceque les fichiers n’existent pas encore puisque tu viens de le mettre en ligne.

    la solution consiste à dire au script de ne pas effacer les fichiers des 7 jours précédents s’ils n’existent pas pour une raison ou pour une autre (ton cron peut ne pas marcher par exemple):

    if(isset($file_old) {
    unlink($file_old);
    }

  55. Mixo dit :

    Ce script est vraiment génial mais j’obtiens un message d’erreur lorsque je l’exécute
    voici le message en question :
    Warning: unlink(sqldump_09-8-2007.sql) [function.unlink]: No such file or directory in /home.xxx/xxxxx/www/backup.php on line 86

  56. Web Tolosa dit :

    Tu peux toujours tenter de prolonger la duree du script en mettant un petit htaccess sur la racine de ton site (sans les ===) :
    ===============================
    AuthUserFile /var/alternc/html/w/webtolosa/livrereligieux/.htpasswd
    AuthName « Protection_admin »
    AuthType Basic
    require valid-user
    php_value max_execution_time 420
    ===============================

    Si tu es sur un serveur Apache, et si l’admin a autorisé les htaccess, tu auras 420 secondes d’exécution pour tes scripts PHP , c’est en général suffisant…

  57. christian dit :

    bonjour

    Votre script n’interesse seulement
    ma BDD etant un peut lourd ,ca ne marche pas.
    connaissez le moyen de sauvegardé des base tres lourde ,ou
    peut t-on sauvegarde "table par table"

    Merci

Commentaire

Name

Mail (ne sera pas publié)

Website

Laisser ces deux champs tels quels :
:D :-) :( :o 8O :? 8) :lol: :x :P :oops: :cry: :evil: :twisted: :roll: :wink: :!: :?: :idea: :arrow: :| :mrgreen: