ChatGPT解决这个技术问题 Extra ChatGPT

我可以从完整的 mysql mysqldump 文件中恢复单个表吗?

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

FWIW,您也可以使用 mydumper。这会创建一个类似 mysqldump 的逻辑转储,但它会为每个表输出单独的文件,并且它可以进行转储和加载多线程,因此花费的时间更少。

M
Mohammad Naji

您可以尝试使用 sed 来仅提取您想要的表。

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

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

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

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


这比我的回答还要好,因为它也处理 CREATE TABLE,但是您应该使用反引号进行搜索,以免得到另一个名为“thisismytabletoo”的表。
真的。我不确定所有 mysql 转储中的表名是否总是被反引号包围,或者是否也可以使用“CREATE TABLE mytable”。如果我们知道转储的样子,我们可以轻松地调整第一个正则表达式。第二个问题可能是表 mytable 不是唯一的(一个在数据库 db1 中,另一个在数据库 db2 中)。两者都将导出到文件 mytable.dump 中。如果表不是唯一的,我们可以使用相同的 sed 命令,首先使用 CREATE DATABASE 以便仅提取正确的数据库。然后,将 sed 命令与 CREATE TABLE 一起使用。
甜的!请记住在顶部添加 DROP TABLE 并在文件底部删除 DROP TABLE [next table]。
对于不添加/删除 DROP TABLE,通过 Table structure for table 注释匹配比通过 CREATE TABLE 匹配更有用。这将确保在忘记删除其 DROP TABLE 语句时不会删除下一个表,并允许管道用于单命令表恢复 (gzip | sed | mysql)。但是,这个解决方案依赖于 mysqldump 注释语法(我不知道它有多标准)。
加上Olexa的修改就完美了:sed -n -e '/Table structure for.*`mytable/,/Table structure for/p' whole.sql > mytable.sql
s
sjas

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

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

这实际上是一个比上面选择的答案更好的解决方案。不敢相信它没有得到更多的支持。
我建议至少在表名中添加反引号:`mytable` 以避免匹配表 mytable2 等等,就像我的情况一样。
你刚刚救了我的屁股
@user706420 嗯,你确定你的终端不应该受到责备吗? sed 不应干扰编码...
对于那些 SQL 文件不包含 DROP TABLE(我的 MySQL 转储没有这个)的人可能想要使用:sed -n -e '/-- Table structure for table ``<Table Name>/,/UNLOCK TABLES/p' <SQL File> > table.sql 这利用了 MySQl 转储中每个表之前提供的表注释,并确保像 {3 这样的行} 被包括在内。
C
Chris Forrence

这可以更轻松地完成吗?我是这样做的:

创建一个临时数据库(例如恢复):

mysqladmin -u root -p 创建恢复

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

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

转储您要恢复的表:

mysqldump 恢复 mytable > mytable.sql

将表导入另一个数据库:

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


这是大多数人需要的。
根据this edit suggestion,您应该添加“--one-database”参数,以确保您只恢复一个数据库并且不破坏其他所有内容。
对于非常大的数据库,这可能非常奇怪——为一张 100 MB 的表恢复 150 GB 的数据。
我只是在没有“--one-database”的情况下运行它,它仍然可以很好地合并表。它没有删除我现有的表格。
非常糟糕的做法!我在转储中的数据库很少,并且只尝试恢复一个,删除了所有其他数据库。
B
Brom558

一个简单的解决方案是简单地创建一个您希望单独恢复的表的转储。您可以使用 mysqldump 命令执行此操作,语法如下:

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

然后正常导入,只会导入转储的表。


J
JCCyC

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

INSERT INTO `the_table_i_want`

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

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


我很愚蠢,因为我没有立即想到 grepping 它。看来,Grep 每天都会保存我的培根。另外两个建议也是非常棒的,如果没有 grep 的奇迹,我完全可以做到这一点。谢谢你们!
如果您认为自己喜欢 grep,那么当您学习 awk 时,您将成为它的快乐性奴隶:en.wikipedia.org/wiki/Awk
v
vicvicvic

备份 $mysqldump -A | gzip > mysqldump -A.gz 恢复单个表 $ mysql -e "truncate TABLE_NAME" DB_NAME $ zgrep ^"INSERT INTO \`TABLE_NAME" mysqldump -A.gz | mysql DB_NAME


M
Maxime Biette

您应该尝试 @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

T
Tim Hoolihan

解决此问题的一种可能方法是恢复到临时数据库,并仅从临时数据库中转储该表。然后使用新脚本。


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

这是比上述其他一些解决方案更好的解决方案,因为并非所有 SQL 转储都包含 DROP TABLE 语句。这将适用于各种转储。


u
user1097790

这个工具可能就是你想要的:tbdba-restore-mysqldump.pl

https://github.com/orczhou/dba-tool/blob/master/tbdba-restore-mysqldump.pl

例如从数据库转储文件中恢复一个表:

tbdba-restore-mysqldump.pl -t yourtable -s yourdb -f backup.sql


M
Madhur Bhaiya

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

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

P
Pjl

这也可能有帮助。

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

B
Bryan Migliorisi

如果您的系统能够满足要求,大多数现代文本编辑器应该能够处理该大小的文本文件。

无论如何,我必须非常快地完成一次,我没有时间找到任何工具。我设置了一个新的 MySQL 实例,导入了整个备份,然后只输出了我想要的表。

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

这很乏味但相当容易。祝你好运。


m
mtoloo

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

vi -o mysql.dump mytable.dump

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

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

我用一个 920 MB 大小的文件完成了它。


C
Community

我尝试了一些选项,但速度非常慢。这会在几分钟内将 360GB 的转储拆分到其表中:

How do I split the output from mysqldump into smaller files?


J
Jad Chahine

前面提到的“sed”解决方案很好,但如上所述不是 100% 安全的

您可能有包含数据的 INSERT 命令:... CREATE TABLE...(whatever)...mytable...

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

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

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

避免使用“.*”并使用“^”来确保我们从行首开始。而且我更愿意抓住最初的“DROP”

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

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

C
Cameron

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


这实际上很容易做到,即使是初学者也可以理解。我不知道,为什么这被否决了。
K
Kuyenda

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

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

查找 /n "for table `" sql.txt

将返回以下内容:

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

[4384]-- 表 my_table 的表结构

[4500]-- 转储表 my_table 的数据

[4514]-- 表 some_other_table 的表结构

... ETC。

这会给你你需要的行号......现在,如果我只知道如何使用它们......调查。


Y
Yagnesh bhalala

您可以使用终端线导入单个表,如下所示。这里将单个用户表导入特定的数据库。

mysql -u root -p -D my_database_name < var/www/html/myproject/tbl_user.sql


从 sql 文件中导入与该数据库相关的所有内容。这个问题是关于从完整的数据库转储中提取单个表。有用...但与这个问题无关
I
InterLinked

我很佩服这里的一些独创性,但实际上根本没有理由使用 sed 来解决 OP 的问题。

注释“use --one-database”是正确的答案,内置于 MySQL/MariaDB。无需第三方黑客。

mysql -u root -p databasename --one-database < localhost.sql 将只导入所需的数据库。

我还发现在某些情况下,当使用它导入一系列数据库时,它会为我在列表中创建下一个数据库(但不会在其中放入任何内容)。不知道为什么这样做,但它使恢复更容易。

使用此命令,以交互方式输入密码,它将导入请求的数据库。


除了 OP 询问是否从单个数据库转储中恢复单个表,而不是从“所有数据库”转储中恢复单个数据库?