使用mysqldump为每行格式化一个插入?

Ken*_*ett 46 mysql mysqldump mysqladministrator mysql-workbench

这已被问过几次,但我无法找到解决问题的方法.基本上当使用mysqldump(MySQL Workbench管理工具的内置工具)时,当我使用扩展插入转储数据库时,我会获得大量的长行数据.我明白为什么会这样做,因为它通过将数据作为一个命令(特别是在InnoDB上)插入来加速插入,但格式化使得真正难以实际查看转储文件中的数据,或者使用diff工具比较两个文件如果你将它们存储在版本控制等等.在我的情况下,我将它们存储在版本控制中,因为我们使用转储文件来跟踪我们的集成测试数据库.

现在我知道我可以关闭扩展插入,所以每行会有一个插入,这是有效的,但是每次使用转储文件进行恢复时它都会变慢.

我的核心问题是,在我转储文件时我们曾经使用过的OLD工具(MySQL管理员),它基本上做了同样的事情,但是它的格式是INSERT语句每行放一个插入,同时仍然进行批量插入.所以不是这样的:

INSERT INTO `coupon_gv_customer` (`customer_id`,`amount`) VALUES (887,'0.0000'),191607,'1.0300');
Run Code Online (Sandbox Code Playgroud)

你得到这个:

INSERT INTO `coupon_gv_customer` (`customer_id`,`amount`) VALUES 
 (887,'0.0000'),
 (191607,'1.0300');
Run Code Online (Sandbox Code Playgroud)

无论我尝试什么选项,似乎没有任何方法可以获得这样的转储,这真的是两全其美.是的,它需要更多的空间,但在需要人来阅读文件的情况下,它会使它变得更有用.

我错过了什么,有一种方法可以使用MySQLDump,或者我们都倒退了,旧的(现已弃用的)MySQL管理员工具中的这个功能不再可用?

小智 34

请尝试使用以下选项: - skip-extended-insert

它对我有用.

  • 在这个问题中排除了`--skip-extended-insert`,因为它使恢复速度变慢. (8认同)
  • 它使恢复更慢但是它更容易和更安全.其他答案可能会因为复杂且容易出错的方法而失败,因为这些方法可能会损坏数据,或者因为在执行sed或执行非常长的mysql查询时出现内存不足问题. (4认同)
  • +1 我正在寻找答案“使用 mysqldump 格式化每行一个插入?”。这个答案对我来说已经足够了。 (2认同)

小智 30

使用默认的mysqldump格式,转储的每个记录将在转储文件(即sql文件)中生成单独的INSERT命令,每个命令都在其自己的行上.这对于源控制(例如,svn,git等)是完美的,因为它使得diff和delta分辨率更精细,并且最终导致更有效的源控制过程.但是,对于大小合适的表,执行所有这些INSERT查询可能会使得从sql文件恢复过于缓慢.

使用--extended-insert选项通过将所有记录包装到转储的sql文件中的单行上的单个INSERT命令来修复多个INSERT问题.但是,源控制过程变得非常低效.整个表内容在sql文件中的一行中表示,如果单个字符在该表中的任何位置发生更改,源控件将标记整个行(即整个表)作为版本之间的差异.而且,对于大型表,这否定了使用正式源控制系统的许多好处.

理想情况下,为了有效地恢复数据库,在sql文件中,我们希望每个表都由一个INSERT表示.对于有效的源控制过程,在sql文件中,我们希望该INSERT命令中的每条记录都驻留在它自己的行上.

我的解决方案是以下备份脚本:

#!/bin/bash

cd my_git_directory/

ARGS="--host=myhostname --user=myusername --password=mypassword --opt --skip-dump-date"
/usr/bin/mysqldump $ARGS --database mydatabase | sed 's$VALUES ($VALUES\n($g' | sed 's$),($),\n($g' > mydatabase.sql

git fetch origin master
git merge origin/master
git add mydatabase.sql
git commit -m "Daily backup."
git push origin master
Run Code Online (Sandbox Code Playgroud)

结果是一个sql文件INSERT命令格式,如下所示:

INSERT INTO `mytable` VALUES
(r1c1value, r1c2value, r1c3value),
(r2c1value, r2c2value, r2c3value),
(r3c1value, r3c2value, r3c3value);
Run Code Online (Sandbox Code Playgroud)

一些说明:

  • 命令行上的密码......我知道,不安全,不同的讨论.
  • --opt:除此之外,打开--extended-insert选项(即每个表一个INSERT).
  • --skip-dump-date:mysqldump通常在创建时在sql文件中放置日期/时间戳.当版本之间的唯一增量是日期/时间戳时,这在源控制中会变得烦人.操作系统和源代码控制系统将对文件和版本进行日期/时间标记.它不是真正需要在sql文件中.
  • git命令不是基本问题(格式化sql文件)的核心,但显示了我如何将我的sql文件恢复到源代码控制中,类似的事情可以用svn完成.将此sql文件格式与您选择的源代码控件结合使用时,您会发现当用户更新其工作副本时,他们只需要在互联网上移动增量(即更改的记录),并且他们可以利用diff实用程序轻松查看数据库中的哪些记录已更改.
  • 如果您正在转储驻留在远程服务器上的数据库,请尽可能在该服务器上运行此脚本,以避免在每次转储时通过网络推送数据库的全部内容.
  • 如果可能,请在运行此脚本的同一服务器上为sql文件建立一个工作源控制存储库; 从那里检查它们到存储库.这也有助于防止每次转储都必须通过网络推送整个数据库.

  • 好方法,但是...问题是备份数据可能包含"VALUES("或"),"行内部.所以正确的方法来防止意外问题是使用另一个工具(不是mysqldump)或修复mysqldump:http:/ /stackoverflow.com/a/20046484/751932 (10认同)

小智 11

正如其他人所说使用sed替换"),"(因为它可以作为数据库中的内容出现而不安全.但是有一种方法可以做到这一点:如果您的数据库名称是my_database,则运行以下命令:

$ mysqldump -u my_db_user -p -h 127.0.0.1 --skip-extended-insert my_database > my_database.sql
$ sed ':a;N;$!ba;s/)\;\nINSERT INTO `[A-Za-z0-9$_]*` VALUES /),\n/g' my_database.sql > my_database2.sql
Run Code Online (Sandbox Code Playgroud)

你也可以使用"sed -i"来替换内联.

以下是此代码正在执行的操作:

  1. --skip-extended-insert将为您拥有的每一行创建一个INSERT INTO.
  2. 现在我们使用sed来清理数据.请注意,使用sed进行常规搜索/替换适用于单行,因此我们无法检测到"\n"字符,因为sed一次只能处理一行.这就是为什么我们把":a; N; $!ba;" 这基本上告诉sed搜索多行并缓冲下一行.

希望这可以帮助


Cri*_*rta 8

使用--tab像这样的选项将转储存储到带有mysqldump的CSV文件中怎么样?

mysqldump --tab=/path/to/serverlocaldir --single-transaction <database> table_a
Run Code Online (Sandbox Code Playgroud)

这会产生两个文件:

  • table_a.sql只包含表create语句; 和
  • table_a.txt 包含制表符分隔的数据.

RESTORING

您可以通过LOAD DATA以下方式恢复您的表

LOAD DATA INFILE '/path/to/serverlocaldir/table_a.txt' 
  INTO TABLE table_a FIELDS TERMINATED BY '\t' ...
Run Code Online (Sandbox Code Playgroud)

LOAD DATA通常比使用INSERT语句快20倍.

如果必须将数据恢复到另一个表中(例如,为了审查或测试目的),您可以创建一个"镜像"表:

CREATE TABLE table_for_test LIKE table_a;
Run Code Online (Sandbox Code Playgroud)

然后将CSV加载到新表中:

LOAD DATA INFILE '/path/to/serverlocaldir/table_a.txt' 
  INTO TABLE table_for_test FIELDS TERMINATED BY '\t' ...
Run Code Online (Sandbox Code Playgroud)

相比

CSV文件是简单的diff文件或里面找,或对非SQL技术的用户谁可以使用常见的工具,如Excel,Access或命令行(diff,comm,等...)


Mik*_*hke 5

我担心这是不可能的.在旧的MySQL管理员中,我编写了用于转储db对象的代码,该代码完全独立于mysqldump工具,因此提供了许多其他选项(如此格式化或进度反馈).在MySQL Workbench中,决定使用mysqldump工具,除了在某些方面倒退并产生版本问题之外,还有一个优点是始终保持与服务器的最新状态.

所以简短的回答是:mysqldump目前无法进行格式化.

  • 太糟糕了.当然这是一个有用的功能,可以添加到mysqldump本身? (2认同)
  • 完全同意!同时我们必须重新发明轮子并编写一个重新格式化的程序^^ ... (2认同)