Vous ne trouvez pas de réponse à votre problème ? Alors posez la question dans le forum. Souvenez-vous qu'il n'y a jamais de question bête, mais rester dans l'ignorance parce que l'on n'ose pas poser une question, ça c'est une erreur !

RESTAURATION DE BASE MYSQL PAR PORTION (POUR EVITER LES DEPASSEMENT DE TIMELIMIT)


Information sur la source

Description

Lorsque l'on effectue une sauvegarde d'une base mysql, le fichier peut etre tres gros. Et quand on le restaure on peut être confronté à la limitation de temps (timeout, timelimit) d'éxecution du script PHP.

Pour contrer cela, ce script de restauration s'arrete automatiquement avant un temps prédéfini, puis relance un nouveau script qui reprend la restauration à l'endroit où elle s'est arrétée dans le script précédent et ainsi de suite jusqu'à ce que le fichier .sql soit lu et restauré en entier.

Les paramètres sont classiques : serveur, nom de base, utilisateur, mot de passe
puis
fichier=nom du fichier sql à restaurer
duree=timeout à ne pas dépasser (5 secondes par défaut)

tout ceci se paramètre en fin de script
 

Source

  • <html>
  • <head><title>Restauration de base MySql</title></head>
  • <body>
  • <?
  • function td() //temp initial
  • {
  • global $TPSDEB,$TPSCOUR;
  • list ($usec,$sec)=explode(" ",microtime());
  • $TPSDEB=$sec;
  • $TPSCOUR=0;
  • }
  • function tf() //temp final ou intermediaire
  • {
  • global $TPSDEB,$TPSCOUR;
  • list ($usec,$sec)=explode(" ",microtime());
  • $TPSFIN=$sec;
  • if (round($TPSFIN-$TPSDEB,1)>=$TPSCOUR+1) //une seconde de plus
  • {
  • $TPSCOUR=round($TPSFIN-$TPSDEB,1);
  • echo $TPSCOUR.".";
  • flush();
  • }
  • }
  • function restoreMySqlDump($dumpFile , $database , $mysqlUser , $mysqlPassword , $hostMySql, $duree)
  • {
  • // $dumpFile, fichier source
  • // $database, nom de la base de données cible
  • // $mysqlUser, login pouyr la connexion au serveur MySql
  • // $mysqlPassword, mot de passe
  • // $histMySql, nom de la machine serveur MySQl
  • // $duree=timeout pour changement de page (-1 = aucun)
  • global $TPSCOUR,$offset,$cpt;
  • $mySqlHandle = mysql_connect($hostMySql, $mysqlUser, $mysqlPassword);
  • if (!$mySqlHandle)
  • {
  • echo "Connexion impossible à $hostMySql pour $mysqlUser";
  • return false;
  • }
  • if(!file_exists($dumpFile))
  • {
  • echo "$dumpFile non trouvé<br>";
  • return FALSE;
  • }
  • $fileHandle = fopen($dumpFile, "rb");
  • if(!$fileHandle)
  • {
  • echo "Ouverture de $dumpFile non trouvé<br>";
  • return FALSE;
  • }
  • if ($offset!=0)
  • {
  • if (fseek($fileHandle,$offset,SEEK_SET)!=0) //erreur
  • {
  • echo "Impossible de trouver l'octet ".number_format($offset,0,""," ")."<br>";
  • return FALSE;
  • }
  • else
  • echo "Reprise à l'octet ".number_format($offset,0,""," ")."<br>";
  • flush();
  • }
  • else
  • {
  • $query = "DROP DATABASE IF EXISTS " . $database;
  • $result = mysql_query($query);
  • $query = "CREATE DATABASE " . $database;
  • $result = mysql_query($query);
  • }
  • $query = "USE " . $database;
  • $result = mysql_query($query);
  • $formattedQuery = "";
  • while(!feof($fileHandle))
  • {
  • tf();
  • if ($duree>0 and $TPSCOUR>=$duree) //on atteint la fin du temps imparti
  • return TRUE;
  • //echo $TPSCOUR."<br>";
  • $buffer=fgets($fileHandle);
  • if (substr($buffer,strlen($buffer),1)==0)
  • $buffer=substr($buffer,0,strlen($buffer)-1);
  • //echo $buffer."<br>";
  • if(substr($buffer, 0, 1) != "#")
  • {
  • $formattedQuery .= $buffer;
  • // echo $formattedQuery."<hr>";
  • if ($formattedQuery)
  • if (mysql_query($formattedQuery)) //réussie sinon continue à conca&téner
  • {
  • $offset=ftell($fileHandle);
  • //echo $offset;
  • $formattedQuery = "";
  • $cpt++;
  • //echo $cpt;
  • }
  • }
  • }
  • if (mysql_error())
  • echo "<hr>ERREUR à partir de [$formattedQuery]<br>".mysql_error()."<hr>";
  • fclose($fileHandle);
  • mysql_close($mySqlHandle);
  • $offset=0;
  • return TRUE;
  • }
  • td(); //initialise le temps
  • if (!isset($offset)) $offset=0; //début de fichier
  • if (!isset($duree)) $duree=5; //timeout de 5 secondes par défaut, -1 pour utiliser sans timeout
  • if (!isset($fichier)) $fichier="sauvebase.sql"; //si le nom du fichier n'est pas en paramètre le mettre ici
  • echo "Restauration de $fichier.<br>Traitement en cours... ";
  • if ($duree>0) echo "timeout de $duree s.<br>";
  • flush();
  • //echo "$offset";
  • //exit;
  • //nom du fichier, nom de la base, nom d'utilisateur, mot de passe, serveur, duree
  • if (restoreMySqlDump($fichier , "base" , "root" , "pass", "localhost",$duree))
  • {
  • if ($offset!=0)
  • {
  • echo "<br>Nombre de requêtes traitées à ce stade : $cpt<br>";
  • echo "<br>mais il faut continuer à l'octet ".number_format($offset,0,""," ");
  • echo "<br>Redirection automatique sinon cliquez <a href=\"restore.php?duree=$duree&offset=$offset&cpt=$cpt\">ici</a>";
  • echo "<script>window.location=\"restore.php?duree=$duree&offset=$offset&cpt=$cpt\";</script>";
  • }
  • else
  • echo "<br>Terminé. Nombre de requêtes totales traitées : $cpt<br>";
  • }
  • ?>
  • </body>
  • </html>
<html>
<head><title>Restauration de base MySql</title></head>
<body>
<?
function td() //temp initial
{
  global $TPSDEB,$TPSCOUR;
  
  
  list ($usec,$sec)=explode(" ",microtime());
  $TPSDEB=$sec;
  $TPSCOUR=0;

}

function tf() //temp final ou intermediaire
{
  global $TPSDEB,$TPSCOUR;
  list ($usec,$sec)=explode(" ",microtime());
  $TPSFIN=$sec;
  if (round($TPSFIN-$TPSDEB,1)>=$TPSCOUR+1) //une seconde de plus
  {
    $TPSCOUR=round($TPSFIN-$TPSDEB,1);
    echo $TPSCOUR.".";
    flush();
  }

}

function restoreMySqlDump($dumpFile , $database , $mysqlUser , $mysqlPassword , $hostMySql, $duree)
{
 // $dumpFile, fichier source
 // $database, nom de la base de données cible
 // $mysqlUser, login pouyr la connexion au serveur MySql
 // $mysqlPassword, mot de passe
 // $histMySql, nom de la machine serveur MySQl
 // $duree=timeout pour changement de page (-1 = aucun)

global $TPSCOUR,$offset,$cpt;

 $mySqlHandle = mysql_connect($hostMySql, $mysqlUser, $mysqlPassword);
 if (!$mySqlHandle)
 {
   echo "Connexion impossible à $hostMySql pour $mysqlUser";
   return false;
 }

 if(!file_exists($dumpFile))
 {
   echo "$dumpFile non trouvé<br>";
   return FALSE;
 }
 $fileHandle = fopen($dumpFile, "rb");

 if(!$fileHandle)
 {
  echo "Ouverture de $dumpFile non trouvé<br>";
  return FALSE;
 }

 if ($offset!=0)
 {
   if (fseek($fileHandle,$offset,SEEK_SET)!=0) //erreur
   {
      echo "Impossible de trouver l'octet ".number_format($offset,0,""," ")."<br>";
      return FALSE;
   }
   else
     echo "Reprise à l'octet ".number_format($offset,0,""," ")."<br>";
  flush();
 }
 else
 {
   $query = "DROP DATABASE IF EXISTS " . $database;
   $result = mysql_query($query);
   $query = "CREATE DATABASE " . $database;
   $result = mysql_query($query);
  }
  
  $query = "USE " . $database;
  $result = mysql_query($query);


 $formattedQuery = "";

 while(!feof($fileHandle))
 {
    tf();
    if ($duree>0 and $TPSCOUR>=$duree) //on atteint la fin du temps imparti
      return TRUE;
    //echo $TPSCOUR."<br>";
    $buffer=fgets($fileHandle);
    if (substr($buffer,strlen($buffer),1)==0)
      $buffer=substr($buffer,0,strlen($buffer)-1);
    
    //echo $buffer."<br>";
    
    if(substr($buffer, 0, 1) != "#")
    {
      $formattedQuery .= $buffer;
       // echo $formattedQuery."<hr>";
      if ($formattedQuery)
        if (mysql_query($formattedQuery)) //réussie sinon continue à conca&téner
        {
          $offset=ftell($fileHandle);
          //echo $offset;
          $formattedQuery = "";
          $cpt++;
          //echo $cpt;
        }
  }
 }

 if (mysql_error())
   echo "<hr>ERREUR à partir de [$formattedQuery]<br>".mysql_error()."<hr>";

 fclose($fileHandle);
 mysql_close($mySqlHandle);
 $offset=0;
 return TRUE;
}


td(); //initialise le temps
if (!isset($offset)) $offset=0; //début de fichier
if (!isset($duree)) $duree=5; //timeout de 5 secondes par défaut, -1 pour utiliser sans timeout

if (!isset($fichier)) $fichier="sauvebase.sql"; //si le nom du fichier n'est pas en paramètre le mettre ici

echo "Restauration de $fichier.<br>Traitement en cours... ";

if ($duree>0) echo "timeout de $duree s.<br>";
flush();
//echo "$offset";
//exit;
//nom du fichier, nom de la base, nom d'utilisateur, mot de passe, serveur, duree
if (restoreMySqlDump($fichier , "base" , "root" , "pass", "localhost",$duree))
{
  if ($offset!=0)
  {
    echo "<br>Nombre de requêtes traitées à ce stade : $cpt<br>";
    echo "<br>mais il faut continuer à l'octet ".number_format($offset,0,""," ");
    echo "<br>Redirection automatique sinon cliquez <a href=\"restore.php?duree=$duree&offset=$offset&cpt=$cpt\">ici</a>";
    echo "<script>window.location=\"restore.php?duree=$duree&offset=$offset&cpt=$cpt\";</script>";
  }
  else
   echo "<br>Terminé. Nombre de requêtes totales traitées : $cpt<br>";

}

?>
</body>
</html>

Conclusion

Le script de restauration est lui meme repris dans les scripts de ce site. Je n'ai fait qu'ajouter la gestion du timeout.

J'ai essayé de mettre un affichage de la progression, mais on ne la voit pas vraiment. Si le javascript est activé, la boucle se fait toute seule il n'y a rien à faire qu'attendre. Sinon en fin de chaque script il y a possibilité de cliquer pour activer le suivant.

 

Commentaires et avis

signaler à un administrateur
Commentaire de Magicking le 06/07/2004 18:51:52

set_time_limit(0);
Et hop tu n'as plus de time limit(c'est fonction n'est pas autorisé partout)

signaler à un administrateur
Commentaire de multicite le 07/11/2005 22:47:02

Bien sûr j'aurais du le préciser... pour les hébergeurs qui bloquent la fonction
set_time_limit(0);

ce qui à mon avis est la majorité...

Je n'ai jamais réussi à faire fonctionner
set_time_limit(0);
qu'en local sur mon serveur et jamais chez un hébergeur... ce serait une belle faille de sécurité

signaler à un administrateur
Commentaire de Shibo_Sources le 17/12/2005 19:59:02

Script super utile, merci!!!
J'aurais bien voulu l'utiliser mais vu que le copier/coller copie aussi le numero de chaque ligne j'ai pas envie de me taper la suppression à la main. Rhalala, bon script + mauvais site mal coder = script qui ne sera jamais utilisé...

signaler à un administrateur
Commentaire de Gantz le 24/07/2006 11:42:00

[Hors sujet]effectivement les numeros de lignes suivent lors d'un copier/coller du code, mais le phenomene ne se produit pas avec Internet Explorer ... chez moi ca ne le fait qu'avec FireFox... sacre renard!

il faudrait un systeme de caddie comme chez nexen.net par exemple

Ajouter un commentaire



Nos sponsors

Sondage...

CalendriCode

Juillet 2009
LMMJVSD
  12345
6789101112
13141516171819
20212223242526
2728293031  

Consulter la suite du CalendriCode

Comparez les prix Nouvelle version

Photothèque Nouveau !



Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés
Temps d'éxécution de la page : 0,374 sec

Google Coop CodeS-SourceS Google Coop CodeS-SourceS


Certaines images présentes sur le site (notament certains avatars) sont issues des collections IconShock, donc si vous souhaitez utiliser ces icons vous devez les acheter, ne les copiez pas et ne utilisez pas dans vos sites et applications sans les avoir commandé.