mysql/mariadb知识点总结(28):mysql备份工具之mysqldump

  • A+
所属分类:mysql  数据库

这篇文章包含了很多知识点,而这些知识点在之前的文章中都已经总结过,所以,如果阅读时遇到障碍请参考之前的文章。

mysql系列文章列表直达链接:mysql知识点总结

 mysql/mariadb知识点总结(28):mysql备份工具之mysqldump

如果你只是想找一些mysqldump语句进行参考,那么,直接查看本文章下方的"mysqldump备份操作小结"部分即可。

如果你想学习怎样使用mysqldump,以及一些常用选项的含义,请按部就班的阅读这篇文章。

 

之前的文章已经描述了与数据库备份有关的常用术语并且简单介绍了mysql中常用的备份工具,如果你还不了解这些知识,请参考如下文章:

数据库备份相关的基础知识

 

之前说过,最好用也最常用的备份工具就是mysqldump和xtrabackup,此处,我们就来总结一下mysqldump的用法。

  

mysqldump简介

mysqldump是mysql自带的逻辑备份工具。

它的备份原理是,通过协议连接到mysql数据库,将需要备份的数据查询出来,将查询出的数据转换成对应的insert语句,当我们需要还原这些数据时,只要执行这些insert语句,即可将对应的数据还原。

 

mysqldump的优点:

可以直接使用文本处理工具处理对应的备份数据,因为备份数据已经被mysqldump转换为了对应的insert语句,所以,我们可以借助文件系统中的文本处理工具对备份数据进行直接处理。

 

mysqldump的缺点:

无法备份索引等信息(因为它只是单纯的将需要备份的数据查询出来,还原后需要重建索引)

当数据为浮点类型时,会出现精度丢失

mysqldump的备份过程属于逻辑备份,备份速度、恢复速度与物理备份工具相比较慢,而且mysqldump备份的过程是串行化的,不会并行的进行备份,如果想要并行备份,可以使用mydumper,但是此处我们不考虑这些,只考虑mysqldump,当数据量较大时,一般不会使用mysqldump进行备份,因为效率较低。

 

mysqldump对innodb存储引擎支持热备,innodb支持事务,我们可以基于事务通过mysqldump对数据库进行热备。

mysqldump对myisam存储引擎只支持温备,通过mysqldump对使用myisam存储引擎的表进行备份时,最多只能实现温备,因为在备份时会对备份的表请求锁,当备份完成后,锁会被释放。

   

初识mysqldump

mysqldump是一个客户端工具,所以当mysqldump连接到数据库时,也会读取mysql数据库的配置文件,加载跟客户端相关的配置。

 

我们先通过一些最简单的实验,来了解一下mysqldump,但是这些操作过于简陋,不足以满足我们的备份需求,备份的数据也有可能出现问题,所以不要使用简单示例中的语句进行备份,我们只是通过它们去了解mysqldump命令罢了,等我们掌握了它,再总结一些实用的备份命令,先来做个小示例。

假设,我们现在想要通过mysqldump备份zsythink数据库,那么,我们可以通过如下mysqldump命令

(注意,如下命令只会显示mysqldump的备份过程,并没有将数据备份,我们慢慢聊)

mysql/mariadb知识点总结(28):mysql备份工具之mysqldump

我们说过mysqldump是一个客户端命令,所以,就像使用mysql命令连接数据库一样,我们需要指定连接的用户名,需要连接的数据库服务IP,以及使用-p选项提示我们输入密码,这些用法都与我们的mysql命令一致,上图中,我们指定要备份zsythink数据库,此时,提示我们输入root用户的密码。

 

输入正确的密码以后,会看到类似如下模样的输出

mysql/mariadb知识点总结(28):mysql备份工具之mysqldump

首先,输出的信息中包含一些注释,这些注释信息中包括mysqldump的版本,mysql的版本,以及主机IP,数据库信息等信息。

除了这些信息,还会输出一些看似注释的可执行意见,比如如下信息。

/*!40101 SET NAMES utf8 */;

那么上述信息有什么用呢?我们来了解一下,因为,mysqldump备份出的信息为可执行的sql,所以,当我们使用这些sql进行数据还原的时候,则必须执行它们,而上述信息表示当mysql版本大于等于4.01.01的时候,才会执行 SET NAMES utf8这条语句,否则这条语句则不会被执行,如果使用mysqldump备份出的sql语句在其他关系型数据库上执行,那么这些信息将被当做注释处理,这是mysql为了使这些sql语句的兼容性更强而使用的一种手段,我们不用过分在意他们。

 

我们要关注的是上图中红色标注的信息。

首先,mysqldump将表a的表结构转换成了对应的sql语句,为了确保还原表a时能够正常的执行创建表的语句,所以,mysqldump自动生成了DROP表a的语句,然后又生成了CREATE表a的语句。完成上述步骤后,mysql开始将表a中的数据转换成对应的sql语句,那么我们看看表a中都有什么数据

mysql/mariadb知识点总结(28):mysql备份工具之mysqldump

表a中只有2条数据,而mysqldump就是将a表中的所有数据转换成了一条insert语句,当我们执行这条insert语句时,就相当于还原了a表数据,当然,上述示例中的insert语句只所以非常少,非常短,是因为我们的示例数据太少了,如果是真正的正在使用的数据库,那么这条insert语句将会非常长,而且,数据库中不只有一张表,因为这是示例,所以我们只截取了一部分进行演示。

 

你一定发现了,当我们执行刚才的mysqldump语句时,所有信息都输出到了屏幕上,并没有保存到任何文件中,所以我们无法通过这些信息对数据进行还原,聪明如你一定想到了,我们只要将这些信息重定向到指定的文件即可,比如,使用用下语句。

mysql/mariadb知识点总结(28):mysql备份工具之mysqldump

我们将备份信息重定向到了zsythinkdb.sql文件中,下次执行这个sql脚本,即可还原zsythink数据库中的所有的表。

 

但是,细心如你一定发现了,此sql脚本中并不包含任何创建数据库的语句,只有创建表的语句,也就是说,在还原时,必须先确保对应的数据库已经存在,那么,我们能不能再备份时就生成创建库的语句呢?必须的额,使用--databases选项指定数据库,即可在备份时生成创建数据库的语句,示例如下。

mysql/mariadb知识点总结(28):mysql备份工具之mysqldump

 

那么,我们能不能只备份数据库中的某张表呢?能不能同时备份指定的多张表呢?能不能一次备份多个数据库呢?必须能啊,只要我们灵活的运用一些选项即可,总结如下。

 

使用如下语句备份zsythink数据库中的所有表,但是不会生成创建zsythink数据库的语句,只是备份其中的表。

mysqldump -uroot -h192.168.1.146 zsythink -p

 

使用如下语句备份zsythink数据库中指定的表,下例中只会备份zsythink数据库中的t1、t2、t3表,其他表不会备份,也不会生成创建zsythink数据库的语句。

mysqldump -uroot -h192.168.1.146 zsythink t1 t2 t3 -p

 

使用如下语句备份zsythink整个数据库,包括其中的所有表,会生成创建zsythink数据库的语句。

mysqldump -uroot -h192.168.1.146 --databases zsythink -p

 

使用如下语句备份指定的多个数据库,所有被指定的数据库中的表都会被备份,对应的创建库的语句也会生成,下例表示同时备份zsythink库与test库。

mysqldump -uroot -h192.168.1.146 --databases zsythink test -p

 

使用如下语句备份当前数据库服务中的所有库。

mysqldump -uroot -h192.168.1.146 --all-databases -p

 

是不是很容易理解,好吧,我们继续。

   

一些常用选项

选项:--master-data

之前说过,在实际进行数据恢复时,往往需要进行时间点还原,通常的做法是先通过最近一次的备份,将数据恢复到备份时的样子,然后再通过二进制日志,将备份之后的更改操作重放一遍,这样就将数据恢复成了最近的模样,比如,备份开始时,二进制日志对应的position为123,那么我们在进行时间点还原时,则需要先通过"备份文件"将数据恢复为备份时的样子,然后再通过二进制日志文件,将position 123之后的所有操作重放一遍。但是,在还原时,我们怎么知道备份时position的值呢?没错,我们必须在备份时就做好标记,在恢复时才知道应该从哪里重放。否则在恢复时,我们则无法获取到重放二进制日志的起始点位置。

其实,备份时二进制日志文件的position非常重要,对于主从复制结构来说,我们同样需要用到它,如果,你的数据库已经运行了一段时间,里面已经存在了一些数据,而此时,你想要将数据库架构从单机架构改为主从架构,你想把当前的主机作为主服务器,然后再新加入一台服务器作为从服务器,那么,一般的做法是将主库中的数据先备份一份出来,然后导入到从库中,但是,当你从主库中备份数据时,往往是热备的,也就是说,备份完成后,有一些操作只在主库中完成了,而备份中却不存在这些数据,所以,我们使用备份在从库中将数据还原以后,还要告诉"从库",将备份之后的操作从"主库"那边同步过来,但是,我们怎么知道从哪里开始同步呢?没错,我们必须在备份的时候就记住它的position,以便告诉从库,从哪里开始同步。其实,这与我们手动重放二进制日志时的场景并没有什么不同,它们的最终目的都是要确定通过备份还原数据以后,要从哪个位置开始执行之后的"重放"或"同步"操作。

 

那么说了这么多,我们怎样才能在备份时,记住binlog对应的position呢?如果你的数据库开启了二进制日志,那么,在使用mysqldump进行备份时,需要使用--master-data选项,标记备份开始时binlog所对应的position(位置),如果你对上述描述不是特别理解,请参考如下连接。

mysql/mariadb知识点总结(25):二进制日志

 

--master-data选项有3个可用值,0、 1 、2,这三个值分别表示不同的含义

此值为0:表示在使用mysqldump进行备份时,不记录对应二进制日志文件位置,将此值显式的设置为0与不使用此选项的效果相同。

此值为1:表示在使用mysqldump进行备份时,记录对应二进制日志文件位置,此值为默认值,也就是说,使用--master-data与使用--master-data=1的效果相同,如果将此选项的值设置为1,则会在备份文件中生成对应的"CHANGE MASTER TO"语句,此语句中标明了备份开始时二进制日志的前缀名以及其所处的position(位置),生成此语句的目的是,在主从复制结构中的"从服务器"中通过备份sql还原数据以后,告诉"从库",从"主库"的二进制日志文件中的哪个位置开始"同步"。如果我们没有使用主从复制结构,同时又想要在备份时记录二进制日志文件的position,则可以将此选项的值设置为2。

此值为2:表示在使用mysqldump进行备份时,记录对应二进制日值文件的位置,如果将此选项的值设置为2,则会在备份文件中生成对应的"CHANGE MASTER TO"语句,此语句中标明了备份开始时二进制日志的前缀名以及其所处的position(位置),但是"CHANGE MASTER TO"语句将会被注释,与此值为1时不同,此选项值为1时,"CHANGE MASTER TO"语句不会被注释,此选项值为2时,"CHANGE MASTER TO"语句会被注释,所以,如果只是单纯的为了记录备份时的二进制日志文件位置,那么将此选项值设置为2即可。

 

那么,我们来动手做个实验,看看加上--master-data选项后,备份文件中到底是什么样子的。

mysql/mariadb知识点总结(28):mysql备份工具之mysqldump

从上图可以看出,如果将--master-data的值指定为1,则会在备份中生成CHANGE MASTER TO语句,而此语句中包含了备份开始时,binlog对应的文件以及position。

但是此语句并未被注释,所以,如果只是单纯的想要获取对应二进制日志文件的位置,则可以将--master-data的值设置为2,如下图所示。

mysql/mariadb知识点总结(28):mysql备份工具之mysqldump

 

选项:--flush-logs

我们再来想另外一个问题,如果,我们将二进制日志的大小设置为600兆,那么,每当二进制日志的大小满600兆,对应的二进制日志文件就会发生滚动,生成一个新的二进制文件,并将原来的600兆保存,假设,我们使用mysqldump对数据库进行备份的那一刻,对应binlog的大小为300兆,也就是说,备份操作开始时,二进制日志文件的position的位置则会处于文件居中的位置,那么,当我们想要找到对应position进行重放时,此位置之前的操作记录对于我们来说都是"无用"的,可是比较尴尬的是,我们还必须找到此位置,这样就会产生一些"多余的工作量",那么我们能不能直接避免这种情况的发生呢?必须的,劳动人民的智慧是无穷的,聪明如你一定想到了,使用一个选项就能搞定,没错,就是一个选项,它就是--flush-logs选项,当我们使用mysqldump进行备份时,如果使用了此选项,备份开始时就会滚动一次二进制日志,无论二进制日志对应的文件大小是否达到600兆,都会滚动,这样,我们就能在对应的二进制日志文件的开头部分开始重放日志了,是不是很高效?有没有很方便?

 

不聊不知道,一个mysqldump命令,竟然要写这么多字,哎·······心累,其实我想说,客官你的留言与评论会使我精力充沛。

 

别着急走,我们还没有聊完······

 

其他常用选项

我们说过,备份的最终目的是"还原",而只备份表中的数据,往往是不够的,因为在数据库中,可能还存在一些存储过程和存储函数、存在一些触发器、事件表,这些"东西"也需要备份,以免最终的备份"不全",在恢复的时候就"懵逼"了,那么,我们来看一些其他的常用的选项,总结如下。

 

--routines选项:表示备份时,存储过程和存储函数也会被备份。

--triggers选项:表示备份时,触发器会被备份。

--events选项:表示备份时,事件表会被备份。

 

  

不同存储引擎下的备份

我们还需要考虑一个问题,如果我们要备份数据,我们一定要保证备份出的数据的可用性,如果备份后的数据在恢复以后,无法正常使用,那么备份出的数据也就失去了备份的意义,数据可用的前提就是数据的正确性、完整性、一致性。

 

而不同的存储引擎,满足一致性时所使用的方法不同,如果你还不明白数据一致性的相关概念,请参考如下文章

mysql/mariadb知识点总结(27):一致性读,快照读

 

那么,我们就来看看使用mysqldump怎样对不同类型的存储引擎进行备份,以满足备份数据的一致性。

 

情况1:表类型为innodb

我们说过,mysqldump支持对innodb存储引擎进行热备,热备的概念我们已经提到过,所谓热备,就是在备份的时候能够对数据库进行读写,但是,如果在备份时对数据库进行读写,怎样保证数据的一致性呢?没错,之前的文章已经详细解释过,如果表类型为innodb,基于"可重读"事务,即可保证热备出的数据的一致性。

如果你不明白为什么,请参考如下文章

http://www.zsythink.net/archives/1436

 

所谓"基于事务"完成备份,就是说所有备份的操作都是在一个"独立的事务"中完成的,而且这个事务的隔离级别为"可重读",其他读写操作是在这个备份事务之外进行的,所以,利用"可重读"事务的"隔离性",即可保证读写操作并不会对备份操作造成影响。

 

因为在<<一致性读,快照读>>这篇文章中已经对原理进行了详细的描述,所以此处不再赘述,直接开始我们的实验。

 

我们先看一下mysql中当前默认的隔离级别

mysql/mariadb知识点总结(28):mysql备份工具之mysqldump

可以看到,当前默认的隔离级别为"读提交",并不是"可重读",那我们需要手动的将当前默认的隔离级别设置为"可重读"吗?不需要,因为mysqldump会自动将备份操作放入一个"可重读"的事务中,即使默认隔离级别不是"可重读"。

 

为了方便理解备份过程,我们将查询日志开启,并且将查询日志存放在general_log表中(如果你不理解下图中变量的含义,请参考http://www.zsythink.net/archives/1246)。

mysql/mariadb知识点总结(28):mysql备份工具之mysqldump

 

好了,万事俱备只欠东风,我们现在就开始备份。

在备份innodb存储引擎的表时,如果想让备份操作基于"独立的事务"进行,则需要使用 --single-transaction选项,示例如下。

mysql/mariadb知识点总结(28):mysql备份工具之mysqldump

使用--single-stransaction选项备份后,查看general_log日志,使用如下语句查看general_log;

select  event_time,thread_id,command_type,argument from mysql.general_log;

从日志中可以看到如下信息,mysqldump自动将备份会话中的事务隔离级别设置为了"可重读",并且开启了一个事务,而且,开始事务时,使用了"WITH CONSISTENT SNAPSHOT",表示事务开始的那一刻,同时创建了快照,以保证备份事务中的"一致性读"。

mysql/mariadb知识点总结(28):mysql备份工具之mysqldump

从上图可以看出,在备份innodb存储引擎的表时,如果使用了--single-transaction选项,mysqldump会自动开启一个"可重读"的事务,基于这个独立的"事务",备份出一个满足一致性的数据备份。

 

所以,如果你的数据库中的所有的表都是使用innodb存储引擎,而且你要对数据库进行热备,那么,则一定要添加上--single-transaction选项,如果开启了二进制日志,也不要忘了设置--master-data选项。

 

情况2:表类型为myisam

如果你数据库中的表使用了myisam存储引擎,那么,在备份时最多只能达到温备的程度,因为myisam存储引擎不支持事务,即使我们使用--single-transaction选项对myisam表进行备份,也不会有任何作用,我们只能通过锁表的方式进行,即在备份开始到备份结束期间,备份的表会被加上读锁,以保证数据的一致性,但是如果你的mysql环境是主从环境,则可以在从服务器上进行备份操作,此处不考虑那么多,我们只要记住,对myisam表进行备份时,需要加锁以保证数据一致性即可。

 

对所有数据备份时,可以使用--lock-all-tables选项,对所有库的所有表加读锁,--lock-all-tables对应的短选项为-x,而且,此选项与--single-transaction选项不能同时存在,示例如下。

mysqldump -uroot -h192.168.1.146 --lock-all-tables --all-databases -p > dbbackup.sql

 

对指定的数据库进行备份时,可以使用--lock-tables选项,对指定库的所有表加锁,--lock-tables对应的短选项为-l,注意,此选项与--single-transaction选项同时存在时,此选项将失效,示例如下

mysqldump -uroot -h192.168.1.146 --lock-tables --databases zsythink -p > zsythink.sql

 

当然,我们也可以使用上述语句对innodb存储引擎的表进行备份,不过这样就不是热备了,而是温备。

 

 

mysqldump备份操作小结

我知道你很懒,好吧,那我就把上文中的常用选项整理成一些常用的sql语句,方便你参考吧。

mysql/mariadb知识点总结(28):mysql备份工具之mysqldump

表使用innodb存储引擎时常用的备份语句

如果未开启二进制日志,备份指定的zsythink数据库,可以使用如下语句。

 

在开启二进制日志的情况下,备份指定的zsythink数据库,通常使用如下语句。

 

在开启二进制日志的情况下,备份所有数据库,通常使用如下语句。

 

表使用myisam存储引擎时常用的备份语句

如果未开启二进制日志,备份指定的zsythink数据库,可以使用如下语句。

 

在开启二进制日志的情况下,备份指定的zsythink数据库,通常使用如下语句。

 

在开启二进制日志的情况下,备份所有数据库,通常使用如下语句。

   

使用mysqldump备份出的数据进行恢复

假设,管理员误操作数据库,drop了zsythink数据库,现在需要回复,那么,可以参考如下过程。

 

通过管理员账号登录mysql

因为恢复数据时会执行大量的insert语句,如果没有特殊要求,还原时没有必要将这些操作记录到二进制日志中,所以关闭当前会话的二进制日志记录。

set sql_log_bin=OFF;

注意:所有恢复操作完成后,最好将当前会话中的sql_log_bin再次开启。

 

假设,通过mysqldump备份的出的zsythink数据库的数据文件存放在/testdir目录下,那么,可以在mysql提示符中使用如下命令,执行对应的sql文件。

\. /testdir/zsythink.sql

上述备份sql文件执行完毕后,zsythink数据库已经恢复到了备份sql对应的时间点,如果不进行时间点恢复,那么做到这一步就算完成了恢复工作,但是我们往往需要进行时间点还原。

 

进行时间点恢复时,备份时间点之后的数据则需要通过二进制日志进行还原,首先,要从二进制日志中提取对应的sql,提取sql的起始位置为备份开始时那一刻二进制文件对应的position,因为在使用mysldump备份时,我们推荐使用--master-data=2选项,所以在对应的数据库备份sql文件中应该存在对应的position,提取sql的结束位置应该是drop语句对应的位置,因为咱们模拟的场景是有人误操作drop了数据库,所以结束位置应该是drop语句的位置。注意,不要把误操作的drop语句提取出来,否则重放对应sql时又会将对应的数据删除,如果是那样就前功尽弃了。我们会对上述过程单独总结为一篇文章,所以此处就不详细描述了。

 

 

好了,mysqldump的相关总结就到这里,希望这篇文章能对你有所帮助,求评论、求点赞、求收藏、求推荐,常来光顾呦,亲,么么哒~~~

 

weinxin
我的微信公众号
关注"实用运维笔记"微信公众号,当博客中有新文章时,可第一时间得知哦~
朱双印

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

目前评论:8   其中:访客  4   博主  4

    • avatar robert 0

      好多干货,学习了,
      有个问题, 为啥我用mysqldump备份和恢复的表, 恢复后的表索引还在呢?
      是mysqldump帮我重建索引了吗? 表是myisam类型的

        • avatar 朱双印 Admin

          @robert 这点我也不是特别明白,回来学习一下具体细节,谢谢捧场,常来呦~~

        • avatar 我的电脑 3

          mysqldump总是难以记住。

          • avatar echo 5

            代表本周打卡 :mrgreen:

            • avatar 妞妞 3

              666 六六六