这已被问过几次,但我无法找到解决问题的方法。基本上当使用mysqldump(MySQL Workbench管理工具的内置工具)时,当我使用扩展插入转储数据库时,我会得到大量的长数据。我明白为什么会这样做,因为它通过将数据作为一个命令(特别是在InnoDB上)插入来加速插入,但格式化使得真正难以实际查看转储文件中的数据,或者使用diff工具比较两个文件如果你将它们存储在版本控制等中。在我的情况下,我将它们存储在版本控制中,因为我们使用转储文件来跟踪我们的集成测试数据库。
现在我知道我可以关闭扩展插入,所以每行会有一个插入,这可以工作,但是每次使用转储文件进行恢复时都会慢一些。
我的核心问题是,在我转储文件时我们曾经使用过的OLD工具(MySQL管理员),它基本上做了同样的事情,但它使用INSERT语句格式化每行插入一个插件,同时仍然进行批量插入。所以不要这样:
INSERT INTO `coupon_gv_customer` (`customer_id`,`amount`) VALUES (887,'0.0000'),191607,'1.0300');
你明白了:
INSERT INTO `coupon_gv_customer` (`customer_id`,`amount`) VALUES
(887,'0.0000'),
(191607,'1.0300');
无论我尝试什么选项,似乎没有任何方法可以获得这样的转储,这真的是两全其美。是的,它需要更多的空间,但在需要人来阅读文件的情况下,它会使它变得更有用。
我是否遗漏了某些内容,并且有一种方法可以使用MySQLDump执行此操作,或者我们都已经倒退了,旧的(现已弃用的)MySQL管理员工具中的此功能不再可用?
答案 0 :(得分:34)
尝试使用以下选项: 的 - 跳过扩展嵌强>
它对我有用。
答案 1 :(得分:29)
使用默认的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
结果是一个sql文件INSERT命令格式,如下所示:
INSERT INTO `mytable` VALUES
(r1c1value, r1c2value, r1c3value),
(r2c1value, r2c2value, r2c3value),
(r3c1value, r3c2value, r3c3value);
一些注意事项:
答案 2 :(得分: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
你也可以使用" sed -i"替换内联。
以下是此代码的用途:
希望这有帮助
答案 3 :(得分:8)
如何使用像这样的--tab
选项将转储存储到带有mysqldump的CSV文件中?
mysqldump --tab=/path/to/serverlocaldir --single-transaction <database> table_a
这会生成两个文件:
table_a.sql
仅包含表create语句;和table_a.txt
包含以制表符分隔的数据。您可以通过LOAD DATA
恢复您的表格:
LOAD DATA INFILE '/path/to/serverlocaldir/table_a.txt'
INTO TABLE table_a FIELDS TERMINATED BY '\t' ...
LOAD DATA通常比使用INSERT语句快20倍。
如果您必须将数据恢复到另一个表格中(例如,为了审查或测试目的),您可以创建一个“镜像”表:
CREATE TABLE table_for_test LIKE table_a;
然后将CSV加载到新表中:
LOAD DATA INFILE '/path/to/serverlocaldir/table_a.txt'
INTO TABLE table_for_test FIELDS TERMINATED BY '\t' ...
CSV文件最适合差异或查找内部,或者非SQL技术用户可以使用常见工具,如Excel
,Access
或命令行(diff
,{ {1}}等等......)
答案 4 :(得分:5)
我担心这是不可能的。在旧的MySQL管理员中,我编写了用于转储db对象的代码,该代码完全独立于mysqldump工具,因此提供了许多其他选项(如此格式化或进度反馈)。在MySQL Workbench中,决定使用mysqldump工具,除了在某些方面倒退并产生版本问题之外,还有一个优势就是始终保持与服务器的最新状态。
所以简短的回答是:mysqldump目前无法进行格式化。
答案 5 :(得分:1)
我发现这个工具对于处理扩展插入非常有用:http://blog.lavoie.sl/2014/06/split-mysqldump-extended-inserts.html
它解析mysqldump输出并在每条记录后插入换行符,但仍然使用更快的扩展插入。与sed脚本不同,如果正则表达式恰好在字符串内匹配,则不应该有任何在错误位置断行的风险。
答案 6 :(得分:0)
我喜欢使用sed的Ace.Di解决方案,直到我收到此错误: sed:无法重新分配内存
因此我不得不写一个小的PHP脚本
mysqldump -u my_db_user -p -h 127.0.0.1 --skip-extended-insert my_database | php mysqlconcatinserts.php > db.sql
PHP脚本还为每个10.000行生成一个新的INSERT,以避免内存问题。
mysqlconcatinserts.php:
#!/usr/bin/php
<?php
/* assuming a mysqldump using --skip-extended-insert */
$last = '';
$count = 0;
$maxinserts = 10000;
while($l = fgets(STDIN)){
if ( preg_match('/^(INSERT INTO .* VALUES) (.*);/',$l,$s) )
{
if ( $last != $s[1] || $count > $maxinserts )
{
if ( $count > $maxinserts ) // Limit the inserts
echo ";\n";
echo "$s[1] ";
$comma = '';
$last = $s[1];
$count = 0;
}
echo "$comma$s[2]";
$comma = ",\n";
} elseif ( $last != '' ) {
$last = '';
echo ";\n";
}
$count++;
}
答案 7 :(得分:0)
尝试一下:
mysqldump -c -t --add-drop-table=FALSE --skip-extended-insert -uroot -p<Password> databaseName tableName >c:\path\nameDumpFile.sql
答案 8 :(得分:0)
添加
set autocommit=0;
到您的sql脚本文件的第一行,然后通过以下方式导入:
mysql -u<user> -p<password> --default-character-set=utf8 db_name < <path>\xxx.sql
,它会快10倍。