mysqldump的一点使用总结(r12笔记第81天)

时间:2022-05-05
本文章向大家介绍mysqldump的一点使用总结(r12笔记第81天),主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

MySQL里的mysqldump无疑是大家使用最为广泛的备份恢复工具了。这样一个工具使用起来功能非常丰富,很多功能几个参数组合起来就能够轻松实现了,我就简单列举几个不错的点。

--master-data

这个选项在搭建主从的时候经常需要考虑,而有了GTID,这个工作一下子轻松了很多,如果需要使用我们总是会使用maser-data=2来导出,1和2是什么区别,简单来看,区别不大,但是差别很明显。

2的情况 -- CHANGE MASTER TO MASTER_LOG_FILE='binlog.000033', MASTER_LOG_POS=943935226; 1的情况 CHANGE MASTER TO MASTER_LOG_FILE='binlog.000033', MASTER_LOG_POS=943935226;

--order-by-primary

这个选项属于MySQL很有特色的一个功能,能够根据主键值来进行排序,这样得到的数据看起来就更加规整了。

----skip-extended-insert

如果要得到一行数据对应一条insert语句的形式,使用这个选项就可以搞定。默认是使用insert into xxx values(xx)(xx)的形式。

INSERT INTO `test` VALUES (1,'1'); INSERT INTO `test` VALUES (2,'2'); INSERT INTO `test` VALUES (3,'3'); INSERT INTO `test` VALUES (5,'5');

--add-drop-database 如果在数据恢复的时候,数据库已经存在则删除重建的情况,使用这个选项就很有用,而在表级默认就不需要了,因为默认是打开了--add-drop-table选项。

Variables (--variable-name=value) and boolean options {FALSE|TRUE} Value (after reading options) --------------------------------- ---- all-databases FALSE all-tablespaces FALSE no-tablespaces FALSE add-drop-database FALSE add-drop-table TRUE

当然对于这个选项,我们得多说说,在最后来引申一个bug。

--replace

这个选项可以生成replace语句而非insert语句,在一些特定的场景中尤其有用。如果出现了数据冲突的情况,需要merge数据,使用replace选项就是一个很不错的选择,而我们也承上启下,比如想一行数据生辰过一条replace语句,那么就可以结合--skip-extended-insert来完成,这样一来就会生成若干条replace语句。

REPLACE INTO `test` VALUES (1,'aa'); REPLACE INTO `test` VALUES (2,'bb');

--complete-insert

这个选项简直台酸爽了,可以生成一个完整的列值映射关系。

INSERT INTO `test` (`id`, `name`) VALUES (1,'aa'),(2,'bb');

或者结合--skip-extended-insert生成多条语句。

INSERT INTO `test` (`id`, `name`) VALUES (1,'aa'); INSERT INTO `test` (`id`, `name`) VALUES (2,'bb');

一个bug

其实mysqldump导出数据的过程还是比较清晰的,只是多了一些更加丰富的功能来修饰。但是也在测试的过程汇总发现了--add-drop-database的一个bug,说起来关系就一下子很微妙了。

如果你需要把某个数据库的数据恢复到指定的备份,如果是全部数据的恢复,包括数据字典数据等,那么使用mysqldump的时候--add-drop-database选项就尤其关键了。

我在使用mysqldup --all-databases --add-drop-database的方式导出数据,导入恢复的时候,收到一个错误信息。

ERROR 1580 (HY000): You cannot 'DROP' a log table if logging is enabled

这样一个问题,看起来很诡异,如果是使用source的方式来执行,基本上会淹没在大批量的日志中。而使用管道的方式也好不到哪里,因为这个错误是完全相同的。

为什么会有这个问题呢,是在mysql这个数据库中存在两个表slow_log,general_log(它们的存储引擎是csv的)。我们的数据库基本都开启了慢日志选项slow_query_log,在启用的时候,如果尝试drop这个表就会抛出错误,这一点上来看,这个处理确实有些别扭,而查找mysql的bug库还真有一个匹配的bug。https://bugs.mysql.com/bug.php?id=69953

而目前的解决方案就有很多了,如果想尽可能平滑实现这个功能,那就是修改导出的sql文件,把drop database if exists mysql这句给去掉,听起来比较笨重,或者修改mysqldump.c,相当于在代码层面加一层过滤。可以参考丁奇的一篇博客。https://m.aliyun.com/yunqi/articles/8721

而如果你使用一点小技巧,比如导入数据前,关掉slow_log,导入后开启,那么导入后就开启不了了,会提示表不存在,无法开启,这样看来,你还得单独再对此做一个备份,想想都头疼。