mysqldump可靠地处理二进制数据吗?

时间:2013-05-15 07:22:33

标签: mysql mysqldump binary-data

我在MySQL 5.6中有一些表在某些字段中包含大量二进制数据。我想知道我是否可以信任mysqldump创建的转储,并确保在通过FTP,SCP等系统传输转储文件时,这些二进制字段不会轻易损坏。另外,我是否应强制此类系统将转储文件视为二进制传输而不是ascii?

提前感谢任何评论!

3 个答案:

答案 0 :(得分:31)

不,当你有二进制blob时,它并不总是可靠的。在这种情况下,你必须使用" - hex-blob "标记以获得正确的结果。

我遇到这些调用失败的情况(在不同的服务器上导入,但都运行Centos6 / MariaDB 10):

mysqldump --single-transaction --routines --databases myalarm -uroot -p"PASSWORD" | gzip > /FILENAME.sql.gz
gunzip < FILENAME.sql.gz | mysql -p"PASSWORD" -uroot --comments

它生成一个无提示无法导入的文件。添加&#34; - skip-extended-insert&#34;给我一个更容易调试的文件,我发现这行已生成但无法读取(但导出或导入时没有报告错误):

INSERT INTO `panels` VALUES (1003,1,257126,141,6562,1,88891,'??\\\?ŖeV???,NULL);

请注意,原始文件中缺少二进制数据的终止引号。

select hex(packet_key) from panels where id=1003;
--> DE77CF5C075CE002C596176556AAF9ED

该列是二进制数据:

CREATE TABLE `panels` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `enabled` tinyint(1) NOT NULL DEFAULT '1',
  `serial_number` int(10) unsigned NOT NULL,
  `panel_types_id` int(11) NOT NULL,
  `all_panels_id` int(11) NOT NULL,
  `installers_id` int(11) DEFAULT NULL,
  `users_id` int(11) DEFAULT NULL,
  `packet_key` binary(16) NOT NULL,
  `user_deleted` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`),
  ...

所以不,你不仅不一定信任mysqldump,你甚至不能依赖它来报告错误。

我使用的一个丑陋的解决方法是mysqldump,通过向转储添加这样的选项来排除两个受影响的表:

--ignore-table=myalarm.panels 

然后这个BASH脚本破解。基本上运行一个SELECT,它产生INSERT值,其中处理NULL列,二进制列变成UNHEX()调用,如下所示:

(123,45678,UNHEX("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"),"2014-03-17 00:00:00",NULL),

如果需要,将其粘贴到您选择的编辑器中以进行播放。

echo "SET UNIQUE_CHECKS=0;SET FOREIGN_KEY_CHECKS=0;DELETE FROM panels;INSERT INTO panels VALUES " > all.sql
mysql -uroot -p"PASSWORD" databasename -e "SELECT CONCAT('(',id,',', enabled,',', serial_number,',', panel_types_id,',', all_panels_id,',', IFNULL(CONVERT(installers_id,CHAR(20)),'NULL'),',', IFNULL(CONVERT(users_id,CHAR(20)),'NULL'), ',UNHEX(\"',HEX(packet_key),'\"),', IF(ISNULL(user_deleted),'NULL',CONCAT('\"', user_deleted,'\"')),'),') FROM panels" >> all.sql
echo "SET UNIQUE_CHECKS=1;SET FOREIGN_KEY_CHECKS=1;" > all.sql

这给了我一个名为&#34; all.sql&#34;的文件。需要INSERT中的最后一个逗号变为分号,然后它可以像上面那样运行。我需要&#34;大导入缓冲区&#34;交互式mysql shell和命令行中都设置了调整来处理该文件,因为它很大。

mysql ... --max_allowed_packet=1GB

当我报告错误时,我最终指向了&#34; - hex-blob&#34;旗帜,它与我的解决方法一样,但从我的方面来说是微不足道的。添加该选项,blob将以十六进制形式转储,结束。

答案 1 :(得分:6)

mysqldump生成的转储可以信任。

为避免编码,二进制传输等问题,请使用--hex-blob选项,以便将每个字节转换为十六进制数字(例如,&#39; abc&#39;变为0x616263)。它会使转储更大,但它将是获得信息的最兼容和最安全的方式(因为它将是纯文本,由于文本文件上的二进制数据生成的特殊符号,没有奇怪的误解。)

您可以确保将其打包在rar或zip文件中的转储文件的完整性(并加快传输速度)。通过这种方式,您可以轻松地检测到它没有被传输损坏。

当您尝试在服务器上加载它时,请检查您是否已在my.cnf服务器配置文件中分配

[mysqld]
max_allowed_packet=600M

或更多,如果需要。

BTW现在我刚刚进行了迁移,并使用mysqldump转储了大量二进制数据,并且运行良好。

答案 2 :(得分:-4)

是的,您可以信任mysqldump生成的转储。

是的,您应该使用二进制传输,以避免在传输过程中进行任何编码转换。 MySQL转储将控制命令添加到转储,以便服务器在重新导入时以特定编码解释文件。您不想更改此编码。