Mysql
 sql >> Base de données >  >> RDS >> Mysql

Fonction de sauvegardes PDO MySQL

Ce script de sauvegarde est ridicule et personne ne devrait en faire une autre version. J'ai déjà vu ce script, ainsi que des tentatives similaires, et ils ont beaucoup de problèmes :

  • Ne délimite pas les noms de table en back-ticks
  • Ne gère pas les valeurs NULL
  • Ne gère pas les jeux de caractères
  • Ne gère pas les données binaires
  • Ne sauvegarde pas les VIEWs
  • Ne sauvegarde pas les déclencheurs ou les procédures stockées ou les fonctions stockées ou les événements
  • Utilise une extension mysql obsolète (mais c'est pourquoi vous voulez une version PDO, n'est-ce pas ?)
  • Utilise adslashes() au lieu d'une fonction d'échappement MySQL appropriée.
  • Ajoute tous données pour tous tables en une très longue chaîne, avant de sortir tout le contenu. Cela signifie que vous devez être en mesure de stocker l'intégralité de votre base de données dans une seule chaîne, ce qui dépassera certainement votre limite de mémoire maximale PHP.

Voir aussi ma réponse précédente sur le malheureux script de sauvegarde de David Walsh :

Concernant votre commentaire :

Lisez les commentaires sur la page à laquelle vous avez lié. Beaucoup de gens ont identifié des problèmes, et certains ont des correctifs ou au moins des suggestions.

Le fait que ce script ajoute tout dans une seule chaîne est un facteur décisif, je pense, mais il ne devrait pas être difficile de modifier le script pour ouvrir le fichier de sortie d'abord , puis affichez les données de chaque ligne pendant la boucle, puis fermez le fichier après la boucle. C'est un peu une évidence, je ne sais pas pourquoi le script ne le fait pas. Mais il est assez clair que le script n'a pas été très bien testé.

Mais de toute façon, je n'essaierais pas de réinventer cette roue. Mysqldump ou mydumper font bien ce travail. FWIW, vous n'avez pas besoin d'exécuter mysqldump sur le même serveur où réside la base de données. Mysqldump prend en charge une option pour --host vous pouvez donc exécuter mysqldump n'importe où pour sauvegarder une base de données distante, tant que les pare-feu n'empêchent pas votre client de se connecter. Fondamentalement, si vous pouvez connecter une application PHP à la base de données à partir d'un hôte client, vous pouvez connecter mysqldump.

Si ce n'est vraiment pas une option, j'utiliserais la fonction de vidage de la base de données de phpmyadmin. Ceux-ci sont matures et bien testés et ils vident tout correctement. Voici un article décrivant comment utiliser la fonctionnalité de vidage :

http://www.techrepublic. com/blog/smb-technologist/import-and-export-databases-using-phpmyadmin/

[Copiant mes commentaires à partir de votre réponse :]

Cela entre dans la révision du code, ce qui n'est pas le but de StackOverflow. Mais brièvement :

  • pas de support approprié pour NULL (vous les convertissez en '');
  • ne délimite pas systématiquement les noms de table ;
  • utiliser des guillemets doubles non-ANSI comme délimiteurs de chaîne ;
  • l'utilisation de requêtes mises en mémoire tampon sur d'énormes tables dépassera la limite de mémoire maximale de PHP ;
  • ajouter toutes les lignes d'une immense table brisera la limite de mémoire maximale de PHP ;
  • en utilisant addslashes() au lieu de PDO::quote();
  • vérifier les erreurs de requête uniquement à la fin de la fonction ;
  • ne vérifie pas l'échec de la création de fichier ;
  • l'extension gzip n'est peut-être pas chargée
  • En outre, ne prend probablement toujours pas en charge les données UTF8.

Oui, c'est mieux que le script original de David Walsh. :-)

NULL n'est pas la même chose que '' dans SQL (sauf dans Oracle, mais ils ne sont pas conformes à la norme SQL dans ce cas). Voir MySQL, mieux vaut insérer NULL ou vide chaîne ?

J'ai mal lu le code sur le problème de limite de mémoire. Vous écrivez une sortie pour chaque ligne, donc ça va (sauf si la ligne contient un blob de 1 Go ou quelque chose).

Mais vous ne devriez pas simplement sortir une seule instruction INSERT avec un ensemble de lignes séparées par des virgules. Même mysqldump --extended-insert produit une longueur finie de données, puis démarre une nouvelle instruction INSERT. Le critère est de savoir si la longueur de l'instruction INSERT correspond à l'argument d'option pour --net-buffer-length .

Dans ANSI SQL, les guillemets simples '' sont utilisés pour délimiter les littéraux de chaîne ou les littéraux de date. Les guillemets doubles "" sont utilisés pour délimiter les identifiants tels que le nom de la table ou les noms de colonne. Par défaut, MySQL les traite de la même manière, mais ce n'est pas standard. Voir Est-ce que différentes bases de données utilisent différentes citations de nom ? . Si vous essayez d'importer vos données de sauvegarde sur un serveur MySQL où vous avez SET SQL_MODE=ANSI_QUOTES , l'importation échouera.

Exemple :query('SELECT * FROM '.$table); et en fait chacun des autres cas où vous utilisez $table dans une requête. Vous n'avez délimité la table qu'une seule fois, dans l'instruction INSERT que votre script affiche.

MySQL reconnaît toujours les back-ticks comme délimiteurs d'identifiant et les guillemets simples pour les chaînes/dates. Mais les guillemets doubles changent de sens en fonction du SQL_MODE que j'ai mentionné. Vous ne pouvez pas supposer quel SQL_MODE est en vigueur sur l'instance MySQL sur laquelle vous restaurez, il est donc préférable d'utiliser les back-ticks pour les identifiants et les guillemets simples pour les chaînes. La raison pour laquelle vous les délimitez lorsque vous interrogez votre table est que vous pourriez avoir des noms de table qui sont des mots réservés SQL, ou qui contiennent des caractères spéciaux, etc.

Vous pouvez insérer tous les types numériques sans délimiteurs. Seules les chaînes et les dates ont besoin de délimiteurs. Voir dev.mysql.com/doc/refman/5.6/en/literals.html