Posso restaurar uma única tabela de um arquivo mysql mysqldump completo?

194

Eu tenho um backup mysqldump do meu banco de dados mysql que consiste em todas as nossas tabelas, que são cerca de 440 megas. Eu quero restaurar o conteúdo de apenas uma das tabelas do mysqldump. Isso é possível? Teoricamente, eu poderia apenas recortar a seção que reconstrói a tabela que eu quero, mas nem sei como editar efetivamente um documento de texto desse tamanho.

Mobius
fonte
2
FWIW, você também pode usar o mydumper . Isso cria um despejo lógico como o mysqldump, mas gera arquivos separados por tabela e pode fazer o despejo e o carregamento com vários threads, portanto, leva menos tempo.
Bill Karwin

Respostas:

289

Você pode tentar usar o sed para extrair apenas a tabela que deseja.

Digamos que o nome da sua tabela seja mytablee o arquivo mysql.dump seja o arquivo que contém seu enorme dump:

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

Isso copiará no arquivo o mytable.dumpque está localizado entre CREATE TABLE mytablee o próximo CREATE TABLEcorrespondente à próxima tabela.

Você pode ajustar o arquivo mytable.dumpque contém a estrutura da tabela mytablee os dados (uma lista de INSERT).

uloBasEI
fonte
5
Isso é ainda melhor do que minha resposta, pois ela também cuida da função CREATE TABLE, mas você deve pesquisar com as aspas para não obter outra tabela chamada "thisismytabletoo".
JCCyC
1
Verdade. Eu não tinha certeza se os nomes de tabela em todos os dumps do mysql estão sempre entre aspas ou se "CREATE TABLE mytable" também poderia ser possível. Podemos adaptar facilmente o primeiro regexp se soubermos como é o despejo. Um segundo problema pode ser se a tabela mytable não for exclusiva (uma no banco de dados db1 e outra no banco de dados db2). Ambos serão exportados no arquivo mytable.dump. Se a tabela não for exclusiva, podemos usar o mesmo comando sed, primeiro com CREATE DATABASE para extrair apenas o banco de dados correto. Em seguida, use o comando sed com CREATE TABLE.
uloBasEI
13
Doce! Lembre-se de adicionar DROP TABLE na parte superior e remova a DROP TABLE [próxima tabela] na parte inferior do arquivo.
21410 Nathan
20
Para não adicionar / remover DROP TABLE, é mais útil corresponder por Table structure for tablecomentário, em vez de corresponder por CREATE TABLE. Isso garantirá que a próxima tabela não seja eliminada se alguém esquecer de remover sua instrução DROP TABLE e permitirá o encaminhamento para a restauração da tabela de comando único (gzip | sed | mysql). No entanto, esta solução depende da sintaxe do comentário do mysqldump (não sei como é padrão).
Olexa
12
Com a modificação do Olexa, é perfeito: sed -n -e '/ Estrutura da tabela para. * `Mytable /, / Estrutura da tabela para / p' whole.sql> mytable.sql
deeenes
120

Eu usei uma versão modificada do comando sed do uloBasEI. Ele inclui o comando DROP anterior e lê até o mysql terminar de descarregar dados para sua tabela (UNLOCK). Trabalhou para mim (re) importar wp_users para um monte de sites do Wordpress.

sed -n -e '/DROP TABLE.*`mytable`/,/UNLOCK TABLES/p' mydump.sql > tabledump.sql
bryn
fonte
3
esta é realmente uma solução muito melhor do que a escolhida como resposta acima. Não acredito que não recebi mais votos.
rich
9
Sugiro adicionar pelo menos citações de backtick ao nome da tabela: `mytable`para evitar tabelas correspondentes mytable2e assim por diante, como foi no meu caso.
bartekbrak
3
você acabou de salvar minha bunda
Gabriel Alack
1
@ user706420 Hmm, você tem certeza de que seu terminal não foi o culpado? sednão deve interferir com a codificação ...
Bryn
6
Para aqueles com arquivos SQL que não contêm o DROP TABLE(meu dump do MySQL não tinha isso), pode querer usar: sed -n -e '/-- Table structure for table ``<Table Name>/,/UNLOCK TABLES/p' <SQL File> > table.sql Isso faz uso dos comentários da tabela fornecidos antes de cada tabela em um dump do MySQl e garante que linhas como /*!40101 SET @saved_cs_client = @@character_set_client */;sejam incluídas.
21716 hamx0r
50

Isso pode ser feito mais facilmente? Foi assim que eu fiz:

Crie um banco de dados temporário (por exemplo, restauração):

mysqladmin -u root -p create restore

Restaure o despejo completo no banco de dados temporário:

mysql -u root -p restore <fulldump.sql

Despejar a tabela que você deseja recuperar:

mysqldump restore mytable> mytable.sql

Importe a tabela em outro banco de dados:

banco de dados mysql -u root -p <mytable.sql

Martijn Kools
fonte
2
É disso que a maioria das pessoas precisa.
S23 /
2
De acordo com esta sugestão de edição , você deve adicionar o parâmetro "--one-database", para restaurar apenas um banco de dados e não destruir todo o resto.
SL Barth - Restabelece Monica
7
Para um banco de dados realmente grande, é muito estranho - restaure 150 GB de dados para uma tabela de 100 MB.
usar o seguinte comando
Eu apenas executei isso sem o "--one-database" e ele ainda mesclou tabelas muito bem. Não removeu minhas tabelas existentes.
Qasim
1
Prática muito ruim! Eu tinha poucos bancos de dados no dump e, tentando restaurar apenas um, excluí todos os outros.
1/16/20 às And:
11

Uma solução simples seria simplesmente criar um despejo da tabela que você deseja restaurar separadamente. Você pode usar o comando mysqldump para fazer isso com a seguinte sintaxe:

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

Em seguida, importe-o normalmente e ele importará apenas a tabela despejada.

Brom558
fonte
9

De uma forma ou de outra, qualquer processo que faça isso terá que percorrer todo o texto do despejo e analisá-lo de alguma forma. Eu apenas saudaria por

INSERT INTO `the_table_i_want`

e canalize a saída no mysql. Dê uma olhada na primeira tabela do despejo antes, para garantir que você esteja recebendo o INSERT da maneira certa.

Edit: OK, conseguiu a formatação correta neste momento.

JCCyC
fonte
Sou burra por não pensar imediatamente em cumprimentá-lo. Grep salva meu bacon todos os dias, ao que parece. As outras duas sugestões também foram incríveis e totalmente o que eu teria feito sem as maravilhas do grep disponíveis. Obrigado a todos!
Mobius
6
Se você acha que ama grep, quando você aprender awk você vai se tornar o feliz escrava sexual: en.wikipedia.org/wiki/Awk
JCCyC
7

Você deve tentar o comando @bryn, mas com o delimitador, caso contrário você também extrairá as tabelas com prefixo ou sufixo, é o que eu costumo fazer:

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

Também para fins de teste, convém alterar o nome da tabela antes de importar:

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

Para importar, você pode usar o comando mysql:

mysql -u root -p'password' mydatabase < mytable_restore.sql
Maxime Biette
fonte
6
  1. Cópia de segurança

    $ mysqldump -A | gzip > mysqldump-A.gz
  2. Restaurar tabela única

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

Uma maneira possível de lidar com isso é restaurar para um banco de dados temporário e despejar apenas essa tabela do banco de dados temporário. Em seguida, use o novo script.

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

Esta é uma solução melhor do que algumas das outras acima, porque nem todos os dumps SQL contêm uma DROP TABLEinstrução. Este vai funcionar todos os tipos de lixões.

Weston Ganger
fonte
2

Isso também pode ajudar.

# 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
fonte
2

A tabela deve apresentar a mesma estrutura no dump e no banco de dados.

`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
fonte
1

A maioria dos editores de texto modernos deve poder manipular um arquivo de texto desse tamanho, se o seu sistema estiver em conformidade.

Enfim, eu tive que fazer isso uma vez muito rapidamente e não tive tempo para encontrar nenhuma ferramenta. Configurei uma nova instância do MySQL, importei todo o backup e cuspi apenas a tabela que eu queria.

Então eu importei essa tabela para o banco de dados principal.

Foi tedioso, mas bastante fácil. Boa sorte.

Bryan Migliorisi
fonte
1

Você pode usar o editor vi. Tipo:

vi -o mysql.dump mytable.dump

para abrir o dump inteiro mysql.dumpe um novo arquivo mytable.dump. Encontre a inserção apropriada na linha pressionando /e digite uma frase, por exemplo: "insira na` mytable` "e copie essa linha usando yy. Alterne para o próximo arquivo ctrl+we down arrow keycole a linha copiada com pp. Por fim, salve o novo arquivo digitando :wqe vi o editor por :q.

Note que se você jogou os dados usando várias inserções você pode copiar (puxão), todos eles de uma vez usando Nyyem que Né o número de linhas a serem copiados.

Eu fiz isso com um arquivo de tamanho de 920 MB.

mtoloo
fonte
0

Obtenha um editor de texto decente como o Notepad ++ ou o Vim (se você já é proficiente). Pesquise o nome da tabela e você poderá destacar apenas os comandos CREATE, ALTER e INSERT dessa tabela. Pode ser mais fácil navegar com o teclado do que com o mouse. E gostaria de garantir que você esteja em uma máquina com bastante RAM ou RAM, para que não haja problemas ao carregar o arquivo inteiro de uma só vez. Depois de destacar e copiar as linhas necessárias, seria uma boa idéia fazer backup apenas da parte copiada em seu próprio arquivo de backup e importá-lo para o MySQL.

Cameron
fonte
1
Isso é realmente muito fácil de fazer e compreensível, mesmo para iniciantes. Eu não sei, por que isso é rebaixado.
Karl Johan Vallner 4/17/17
0

Os blocos do SQL são bloqueados com "Estrutura da tabela para tabela my_table" e "Dump de dados para tabela my_table".

Você pode usar uma linha de comando do Windows da seguinte maneira para obter os números de linha das várias seções. Ajuste a sequência pesquisada conforme necessário.

encontre / n "para a tabela` "sql.txt

O seguinte será retornado:

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

[4384] - Estrutura de tabela para tabela my_table

[4500] - Dados de despejo para tabela my_table

[4514] - Estrutura de mesa para mesa some_other_table

... etc.

Isso te dá os números de linha que você precisa ... agora, se eu soubesse como usá-los ... investigando.

Kuyenda
fonte
0

As soluções 'sed' mencionadas anteriormente são boas, mas como mencionadas, não são 100% seguras

  • Você pode ter comandos INSERT com dados contendo: ... CREATE TABLE ... (tanto faz) ... mytable ...

  • ou mesmo a string exata "CREATE TABLE` mytable`; " se você estiver armazenando comandos DML, por exemplo!

(e se a tabela for grande, você não deseja verificar isso manualmente)

Gostaria de verificar a sintaxe exata da versão de despejo usada e ter uma pesquisa de padrões mais restritiva:

Evite ". *" E use "^" para garantir que começamos no início da linha. E eu preferiria pegar o 'DROP' inicial

Em suma, isso funciona melhor para mim:

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