我可以从完整的mysql mysqldump文件还原单个表吗?


194

我有一个我的mysql数据库的mysqldump备份,其中包含我们所有的表,大约440兆。我想从mysqldump恢复仅其中一张表的内容。这可能吗?从理论上讲,我可以剪掉重建所需表的部分,但我什至不知道如何有效地编辑该大小的文本文档。


2
FWIW,您也可以使用mydumper。这将创建一个类似于mysqldump的逻辑转储,但它会在每个表中输出单独的文件,并且它既可以进行转储也可以进行多线程加载,因此花费的时间更少。
比尔·卡温

Answers:


289

您可以尝试使用sed以便仅提取所需的表。

假设您的表的名称是mytable,文件mysql.dump是包含巨大转储的文件:

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

这将在文件中复制mytable.dump位于CREATE TABLE mytable与下CREATE TABLE一个表相对应的下一个之间的内容。

然后,您可以调整mytable.dump包含表结构mytable和数据(的列表INSERT)的文件。


5
这比我的回答还要好,因为它也处理CREATE TABLE,但是您应该使用反引号进行搜索,以免获得另一个称为“ thisismytabletoo”的表。
JCCyC

1
真正。我不确定所有mysql转储中的表名是否总是被反引号包围,或者“ CREATE TABLE mytable”是否也可能。如果我们知道转储的样子,我们可以轻松地适应第一个正则表达式。第二个问题可能是表mytable不是唯一的(一个在数据库db1中,另一个在数据库db2中)。两者都将导出到文件mytable.dump中。如果表不是唯一的,我们可以使用相同的sed命令,首先使用CREATE DATABASE以便仅提取正确的数据库。然后,将sed命令与CREATE TABLE一起使用。
uloBasEI

13
甜!记住要在文件的顶部添加DROP TABLE,在文件的底部删除DROP TABLE [next table]。
内森2010年

20
对于不添加/删除DROP TABLE的情况,按Table structure for table注释匹配比按CREATE TABLE匹配更有用。这将确保如果忘记删除其DROP TABLE语句,则不会删除下一个表,并允许通过管道进行单命令表还原(gzip | sed | mysql)。但是,此解决方案取决于mysqldump注释语法(我不知道它的标准程度)。
Olexa

12
通过Olexa的修改,它是完美的:sed -n -e'/表结构为* .mytable /,//表结构为/ p'Whole.sql> mytable.sql
2013年

120

我使用了uloBasEI的sed命令的修改版本。它包含前面的DROP命令,并读取直到mysql完成将数据转储到表中(UNLOCK)为止。为我工作(重新)将wp_users导入到多个Wordpress网站。

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

3
这实际上是比上面的答案更好的解决方案。不敢相信它没有得到更多的赞誉。
rICh

9
我建议在表名中至少添加反引号:`mytable`避免与表匹配mytable2,以此类推。
bartekbrak

3
你刚刚救了我的屁股
Gabriel Alack

1
@ user706420嗯,您确定您的终端不应该受到指责吗?sed不应该干扰编码...
bryn 2014年

6
对于那些SQL文件不包含DROP TABLE(我的MySQL转储没有此文件)的用户,可能要使用:sed -n -e '/-- Table structure for table ``<Table Name>/,/UNLOCK TABLES/p' <SQL File> > table.sql 这利用了MySQl转储中每个表之前提供的表注释,并确保/*!40101 SET @saved_cs_client = @@character_set_client */;包含类似行。
hamx0r

50

这可以更容易做到吗?这是我的方法:

创建一个临时数据库(例如,还原):

mysqladmin -u root -p创建还原

恢复临时数据库中的完整转储:

mysql -u root -p恢复<fulldump.sql

转储您要恢复的表:

mysqldump恢复mytable> mytable.sql

将表导入另一个数据库:

mysql -u root -p数据库<mytable.sql


2
这是大多数人需要的。
sjas 2015年

2
根据此编辑建议,您应该添加“ --one-database”参数,以确保仅还原一个数据库并且不会破坏其他所有数据库。
SL Barth-恢复莫妮卡2015年

7
对于真正巨大的数据库,这可能会很奇怪-为一张100 MB的表还原150 GB的数据。
Enyby '16

我只是在没有“ --one-database”的情况下运行了它,但它仍然可以合并表。它没有删除我现有的表。
卡西姆

1
非常不好的做法!我的转储数据库很少,尝试还原仅一个数据库,删除了所有其他数据库。
AndreyP

11

一个简单的解决方案是仅创建您希望单独还原的表的转储。您可以使用mysqldump命令通过以下语法进行操作:

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

然后,像往常一样导入它,它将仅导入转储的表。


9

一种或另一种方式,任何执行此操作的过程都必须遍历转储的整个文本并以某种方式对其进行解析。我只是为了

INSERT INTO `the_table_i_want`

并将输出通过管道传递到mysql中。看一下转储中的第一个表,以确保您以正确的方式使用INSERT。

编辑:好的,这次得到了正确的格式。


我很傻,因为没有立即考虑将其删除。看来,Grep每天都在保存我的培根。其他两个建议也都是爆炸性的建议,如果没有grep的奇迹,我会做的全部。谢谢你们!
Mobius

6
如果您认为自己喜欢grep,则当您学习awk时,您将成为其快乐的性奴隶:en.wikipedia.org/wiki/Awk
JCCyC 2009年

7

您应该尝试@bryn命令,但是使用`分隔符,否则您还将提取具有前缀或后缀的表,这是我通常要做的:

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

同样出于测试目的,您可能需要在导入之前更改表名称:

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

要导入,您可以使用mysql命令:

mysql -u root -p'password' mydatabase < mytable_restore.sql

6
  1. 后备

    $ mysqldump -A | gzip > mysqldump-A.gz
  2. 恢复单表

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



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

与上面的某些其他解决方案相比,这是一种更好的解决方案,因为并非所有的SQL转储都包含一条DROP TABLE语句。这将工作将各种垃圾场。


2

这可能也有帮助。

# 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'

2

在转储和数据库中,表应具有相同的结构。

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

要么

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

1

如果您的系统支持,大多数现代文本编辑器都应该能够处理该大小的文本文件。

无论如何,我不得不非常快地执行一次,而且我没有时间找到任何工具。我设置了一个新的MySQL实例,导入了整个备份,然后只吐出了我想要的表。

然后,我将该表导入了主数据库。

这很乏味但是很容易。祝好运。


1

您可以使用vi编辑器。类型:

vi -o mysql.dump mytable.dump

打开整个转储mysql.dump和一个新文件mytable.dump。按下/,然后输入一个词组,找到合适的插入行,例如:“ insert into`mytable`”,然后使用复制该行yyctrl+w然后切换到下一个文件,并down arrow key用复制粘贴行pp。最后输入,使用,:wq然后使用vi编辑器保存新文件:q

请注意,如果您使用多个插入转储了数据,则可以一次复制(抽出)所有这些数据Nyy,其中使用的N是要复制的行数。

我用920 MB大小的文件完成了此操作。


0

获得像Notepad ++或Vim这样的体面的文本编辑器(如果您已经精通它的话)。搜索表名称,您应该只可以突出显示该表的CREATE,ALTER和INSERT命令。使用键盘而不是鼠标进行导航可能更容易。而且我会确保您使用的机器上有很多内存或RAM,这样就不会立即加载整个文件。突出显示并复制了所需的行后,最好将复制的部分仅备份到其自己的备份文件中,然后将其导入MySQL。


1
实际上,这确实很容易做到,即使是初学者也可以理解。我不知道,为什么这被否决了。
Karl Johan Vallner '17

0

SQL的大块被“表的表结构my_table”和“表的数据转储” 阻止my_table

您可以按照以下方式使用Windows命令行来获取各个部分的行号。根据需要调整搜索到的字符串。

找到/ n“ for table`” sql.txt

将返回以下内容:

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

[4384]-表格的表格结构 my_table

[4500]-转储表数据 my_table

[4514]-表格的表格结构 some_other_table

...等

现在,如果我只知道如何使用它们,便可以获取所需的行号...正在调查。




0

前面提到的“ sed”解决方案不错,但如上所述并非100%安全

  • 您可能有INSERT命令,其数据包含:... CREATE TABLE ...(无论如何)... mytable ...

  • 甚至确切的字符串“ CREATE TABLE`mytable`;” 例如,如果要存储DML命令!

(如果表很大,则您不想手动检查)

我将验证使用的转储版本的确切语法,并进行更严格的模式搜索:

避免使用“。*”并使用“ ^”来确保我们从该行的开头开始。而且我更愿意选择最初的“ DROP”

总而言之,这对我来说更好:

sed -n -e '/^DROP TABLE IF EXISTS \`mytable\`;/,/^UNLOCK TABLES;/p' mysql.dump > mytable.dump
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.