Puis-je restaurer une seule table à partir d'un fichier mysql mysqldump complet?

194

J'ai une sauvegarde mysqldump de ma base de données mysql composée de toutes nos tables qui fait environ 440 mégaoctets. Je veux restaurer le contenu d'une seule des tables du mysqldump. Est-ce possible? Théoriquement, je pourrais simplement couper la section qui reconstruit le tableau que je veux, mais je ne sais même pas comment modifier efficacement un document texte de cette taille.

Mobius
la source
2
FWIW, vous pouvez également utiliser mydumper . Cela crée un vidage logique comme mysqldump, mais il génère des fichiers séparés par table, et il peut effectuer à la fois le vidage et le chargement multi-thread, donc cela prend moins de temps.
Bill Karwin

Réponses:

289

Vous pouvez essayer d'utiliser sed afin d'extraire uniquement la table souhaitée.

Disons que le nom de votre table est mytableet que le fichier mysql.dump est le fichier contenant votre énorme vidage:

$ sed -n -e '/CREATE TABLE.*`mytable`/,/CREATE TABLE/p' mysql.dump > mytable.dump

Cela copiera dans le fichier mytable.dumpce qui se trouve entre CREATE TABLE mytableet le suivant CREATE TABLEcorrespondant au tableau suivant.

Vous pouvez ensuite ajuster le fichier mytable.dumpqui contient la structure de la table mytableet les données (une liste de INSERT).

uloBasEI
la source
5
C'est encore plus agréable que ma réponse car il s'occupe également de la CREATE TABLE, mais vous devriez rechercher avec les guillemets afin de ne pas obtenir une autre table appelée "thisismytabletoo".
JCCyC
1
Vrai. Je n'étais pas sûr si les noms de table dans tous les vidages mysql sont toujours entourés de guillemets ou si "CREATE TABLE mytable" pouvait également être possible. Nous pouvons facilement adapter la première expression rationnelle si nous savons à quoi ressemble le vidage. Un deuxième problème pourrait se poser si la table mytable n'est pas unique (une dans la base de données db1 et une autre dans la base de données db2). Les deux seront exportés dans le fichier mytable.dump. Si la table n'est pas unique, nous pouvons utiliser la même commande sed, d'abord avec CREATE DATABASE afin d'extraire uniquement la bonne base de données. Ensuite, utilisez la commande sed avec CREATE TABLE.
uloBasEI
13
Doux! N'oubliez pas d'ajouter DROP TABLE en haut et de supprimer DROP TABLE [tableau suivant] en bas du fichier.
Nathan
20
Pour ne pas ajouter / supprimer DROP TABLE, il est plus utile de faire correspondre par Table structure for tablecommentaire, au lieu de faire correspondre par CREATE TABLE. Cela garantira que la table suivante ne sera pas supprimée si l'on oublie de supprimer son instruction DROP TABLE et autorise la canalisation pour la restauration de table à commande unique (gzip | sed | mysql). Cependant, cette solution dépend de la syntaxe des commentaires mysqldump (je ne sais pas comment elle est standard).
Olexa
12
Avec la modification d'Olexa, c'est parfait: sed -n -e '/ Structure de table pour. * `Mytable /, / Structure de table pour / p' whole.sql> mytable.sql
deeenes
120

J'ai utilisé une version modifiée de la commande sed de uloBasEI. Il inclut la commande DROP précédente et lit jusqu'à ce que mysql ait terminé de vider les données dans votre table (UNLOCK). A travaillé pour moi (ré) important wp_users vers un tas de sites Wordpress.

sed -n -e '/DROP TABLE.*`mytable`/,/UNLOCK TABLES/p' mydump.sql > tabledump.sql
bryn
la source
3
c'est en fait une bien meilleure solution que celle choisie comme réponse ci-dessus. Je ne peux pas croire que ça n'ait pas eu plus de votes positifs.
rICh
9
Je suggère d'ajouter au moins des guillemets inversés au nom de la table: `mytable`pour éviter de faire correspondre les tables mytable2, etc.
bartekbrak
3
vous venez de sauver mon cul
Gabriel Alack
1
@ user706420 Hmm, êtes-vous certain que votre terminal n'était pas à blâmer? sedne devrait pas interférer avec l'encodage ...
bryn
6
Pour ceux avec des fichiers SQL ne contenant pas le DROP TABLE(mon vidage MySQL ne l'avait pas) peuvent vouloir utiliser: sed -n -e '/-- Table structure for table ``<Table Name>/,/UNLOCK TABLES/p' <SQL File> > table.sql Cela utilise les commentaires de table fournis avant chaque table dans un vidage MySQl, et garantit des lignes comme /*!40101 SET @saved_cs_client = @@character_set_client */;être incluses.
hamx0r
50

Cela peut-il être fait plus facilement? Voici comment je l'ai fait:

Créez une base de données temporaire (par exemple restauration):

mysqladmin -u root -p créer restaurer

Restaurez le vidage complet dans la base de données temporaire:

mysql -u root -p restore <fulldump.sql

Videz la table que vous souhaitez récupérer:

mysqldump restaurer mytable> mytable.sql

Importez la table dans une autre base de données:

mysql -u root -p base de données <mytable.sql

Martijn Kools
la source
2
C'est ce dont la plupart des gens ont besoin.
sjas
2
Selon cette suggestion de modification , vous devez ajouter le paramètre "--one-database", pour vous assurer de ne restaurer qu'une seule base de données et de ne pas détruire tout le reste.
SL Barth - Reinstate Monica
7
Pour une base de données vraiment énorme, cela peut être très étrange - restaurer 150 Go de données pour une table de 100 Mo.
Enyby
Je viens de l'exécuter sans "--one-database" et il a tout de même très bien fusionné les tables. Il n'a pas supprimé mes tables existantes.
Qasim
1
Très mauvaise pratique! J'avais quelques bases de données dans le vidage, et en essayant d'en restaurer une seule, j'ai supprimé toutes les autres.
AndreyP
11

Une solution simple serait de simplement créer un vidage de la table que vous souhaitez restaurer séparément. Vous pouvez utiliser la commande mysqldump pour le faire avec la syntaxe suivante:

mysqldump -u [user] -p[password] [database] [table] > [output_file_name].sql

Ensuite, importez-le comme d'habitude, et il importera uniquement la table sauvegardée.

Brom558
la source
9

D'une manière ou d'une autre, tout processus faisant cela devra parcourir tout le texte du vidage et l'analyser d'une manière ou d'une autre. Je voudrais simplement

INSERT INTO `the_table_i_want`

et canalisez la sortie dans mysql. Jetez un œil à la première table de la décharge avant, pour vous assurer que vous obtenez le INSERT de la bonne façon.

Edit: OK, le formatage est correct cette fois.

JCCyC
la source
Je suis stupide de ne pas penser immédiatement à le saluer. Grep conserve mon bacon tous les jours, semble-t-il. Les deux autres suggestions étaient également des suggestions et totalement ce que j'aurais fait sans les merveilles de grep disponibles. Merci à tous!
Mobius
6
Si vous pensez que vous aimez grep, quand vous apprendrez awk, vous deviendrez son esclave sexuel heureux: en.wikipedia.org/wiki/Awk
JCCyC
7

Vous devriez essayer la commande @bryn mais avec le délimiteur `sinon vous extrairez également les tables ayant un préfixe ou un suffixe, c'est ce que je fais habituellement:

sed -n -e '/DROP TABLE.*`mytable`/,/UNLOCK TABLES/p' dump.sql > mytable.sql

Également à des fins de test, vous souhaiterez peut-être modifier le nom de la table avant d'importer:

sed -n -e 's/`mytable`/`mytable_restored`/g' mytable.sql > mytable_restored.sql

Pour importer, vous pouvez ensuite utiliser la commande mysql:

mysql -u root -p'password' mydatabase < mytable_restore.sql
Maxime Biette
la source
6
  1. Sauvegarde

    $ mysqldump -A | gzip > mysqldump-A.gz
  2. Restaurer une table unique

    $ mysql -e "truncate TABLE_NAME" DB_NAME
    $ zgrep ^"INSERT INTO \`TABLE_NAME" mysqldump-A.gz | mysql DB_NAME
y.tk
la source
4

Une façon possible de résoudre ce problème consiste à restaurer dans une base de données temporaire et à vider uniquement cette table de la base de données temporaire. Utilisez ensuite le nouveau script.

Tim Hoolihan
la source
3
sed -n -e '/-- Table structure for table `my_table_name`/,/UNLOCK TABLES/p' database_file.sql > table_file.sql

Il s'agit d'une meilleure solution que certaines des autres ci-dessus car tous les vidages SQL ne contiennent pas une DROP TABLEinstruction. Celui-ci fonctionnera avec toutes sortes de décharges.

Weston Ganger
la source
2

Cela peut aussi aider.

# mysqldump -u root -p database0 > /tmp/database0.sql
# mysql -u root -p -e 'create database database0_bkp'
# mysql -u root -p database0_bkp < /tmp/database0.sql
# mysql -u root -p database0 -e 'insert into database0.table_you_want select * from database0_bkp.table_you_want'
Pjl
la source
2

La table doit présenter la même structure dans le vidage et la base de données.

`zgrep -a ^"INSERT INTO \`table_name" DbDump-backup.sql.tar.gz | mysql -u<user> -p<password> database_name`

ou

`zgrep -a ^"INSERT INTO \`table_name" DbDump-backup.sql | mysql -u<user> -p<password> database_name`
Neminath
la source
1

La plupart des éditeurs de texte modernes devraient être capables de gérer un fichier texte de cette taille, si votre système est à la hauteur.

Quoi qu'il en soit, j'ai dû le faire une fois très rapidement et je n'ai pas eu le temps de trouver des outils. J'ai mis en place une nouvelle instance MySQL, importé toute la sauvegarde et puis craché juste la table que je voulais.

J'ai ensuite importé cette table dans la base de données principale.

C'était fastidieux mais plutôt facile. Bonne chance.

Bryan Migliorisi
la source
1

Vous pouvez utiliser l'éditeur vi. Type:

vi -o mysql.dump mytable.dump

pour ouvrir à la fois le vidage entier mysql.dumpet un nouveau fichier mytable.dump. Recherchez l'insertion appropriée dans la ligne en appuyant sur /puis tapez une phrase, par exemple: "insérer dans` mytable` ", puis copiez cette ligne à l'aide de yy. Passer au fichier suivant parctrl+wdown arrow key, collez la ligne copiée avec pp. Enfin, enregistrez le nouveau fichier en tapant :wqet tout à fait l'éditeur vi par :q.

Notez que si vous avez déversé les données à l' aide de multiples inserts , vous pouvez copier (Yank) tous à la fois en utilisant Nyydans lequelN le nombre de lignes à copier.

Je l'ai fait avec un fichier de 920 Mo.

mtoloo
la source
0

Obtenez un éditeur de texte décent comme Notepad ++ ou Vim (si vous êtes déjà compétent avec lui). Recherchez le nom de la table et vous devriez pouvoir mettre en surbrillance uniquement les commandes CREATE, ALTER et INSERT pour cette table. Il peut être plus facile de naviguer avec votre clavier plutôt qu'avec une souris. Et je m'assurerais que vous êtes sur une machine avec beaucoup de RAM ou de sorte qu'il n'y aura pas de problème de chargement du fichier entier à la fois. Une fois que vous avez mis en surbrillance et copié les lignes dont vous avez besoin, ce serait une bonne idée de sauvegarder uniquement la partie copiée dans son propre fichier de sauvegarde, puis de l'importer dans MySQL.

Cameron
la source
1
C'est en fait très facile à faire et compréhensible même par les débutants. Je ne sais pas pourquoi cela est sous-voté.
Karl Johan Vallner
0

Les morceaux de SQL sont bloqués avec «Structure de table pour table my_table» et «Dump des données pour table my_table».

Vous pouvez utiliser une ligne de commande Windows comme suit pour obtenir les numéros de ligne pour les différentes sections. Ajustez la chaîne recherchée selon vos besoins.

trouver / n "pour la table" "sql.txt

Les éléments suivants seront retournés:

---------- SQL.TXT

[4384] - Structure de table pour table my_table

[4500] - Données de dumping pour le tableau my_table

[4514] - Structure de table pour table some_other_table

... etc.

Cela vous donne les numéros de ligne dont vous avez besoin ... maintenant, si seulement je savais comment les utiliser ... enquêter.

Kuyenda
la source
0

Les solutions «sed» mentionnées précédemment sont agréables mais, comme mentionné, elles ne sont pas 100% sécurisées

  • Vous pouvez avoir des commandes INSERT avec des données contenant: ... CREATE TABLE ... (n'importe quoi) ... mytable ...

  • ou même la chaîne exacte "CREATE TABLE` mytable`; " si vous stockez des commandes DML par exemple!

(et si le tableau est énorme, vous ne voulez pas le vérifier manuellement)

Je vérifierais la syntaxe exacte de la version de vidage utilisée et aurais une recherche de modèle plus restrictive:

Évitez ". *" Et utilisez "^" pour vous assurer que nous commençons au début de la ligne. Et je préfère saisir le «DROP» initial

Dans l'ensemble, cela fonctionne mieux pour moi:

sed -n -e '/^DROP TABLE IF EXISTS \`mytable\`;/,/^UNLOCK TABLES;/p' mysql.dump > mytable.dump
phil_w
la source