您的位置:首页 > 博客中心 > 数据库 >

ch5 MySQL 备份与恢复

时间:2022-03-14 03:03

第 5 章 MySQL 备份与恢复

前言

数据库的备份与恢复一直都是 DBA 工作中最为重要的部分之一,也是基本工作之一。任何正式环境的数据库都必须有完整的备份计划和恢复测试,本章内容将主要介绍 MySQL 数据库的备份与恢复相关内容。

5.1 数据库备份使用场景

你真的明白了自己所做的数据库备份是要面对什么样的场景的吗?

我想任何一位维护过数据库的人都知道数据库是需要备份的,也知道备份数据库是数据库维护必不可少的一件事情。那么是否每一个人都知道自己所做的备份到底是为了应对哪些场景的呢?抑或者说我们每个人是否都很清楚的知道,为什么一个数据库需要作备份呢?读到这里,我想很多读者朋友都会嗤之以鼻,"备份的作用不就是为了防止原数据丢失吗,这谁不知道?"。确实,数据库的备份很大程度上的作用,就是当我们的数据库因为某些原因而造成部分或者全部数据丢失后,方便找回丢失的数据。但是,不同类型的数据库备份,所能应付情况是不一样的,而且,数据库的备份同时也还具有其他很多的作用。而且我想,每个人对数据库备份的作用的理解可能都会有部分区别。

下面我就列举一下我个人理解的我们能够需要用到数据库备份的一些比较常见的情况吧。

一、数据丢失应用场景

1、人为操作失误造成某些数据被误操作; 2、软件 BUG 造成数据部分或者全部丢失;

    ????可以将字段的内容"包装"起来的"FIELDS????[OPTIONALLY]????ENCLOSED????BY????‘name‘",如

    果不使用"OPTIONALLY"则包括数字类型的所有类型数据都会被"包装",使 用"OPTIONALLY" 之后,则数字类型的数据不会被指定字符"包装"。

    通过"FIELDS????TERMINATED????BY"可以设定每两个字段之间的分隔符;而通过"LINES????TERMINATED????BY"则会告诉 MySQL 输出文件在每条记录结束的时候需要

    添加什么字符。

    如以下示例:

    ????root@localhost :????test????10:02:02>????SELECT????*????INTO????OUTFILE????‘/tmp/dump.text‘

    ????->????FIELDS????TERMINATED????BY????‘,‘????OPTIONALLY????ENCLOSED????BY????‘"‘

    ????->????LINES????TERMINATED????BY????‘\n‘

    ->????FROM????test_outfile????limit????100; Query????OK,????100????rows????affected????(0.00????sec)

    root@localhost :????test????10:02:11>????exit Bye root@sky:/tmp# cat????dump.text

    350021,21,"A","abcd"

    350022,22,"B","abcd"

    350023,23,"C","abcd"

    350024,24,"D","abcd"

    350025,25,"A","abcd" ...????...

    2、通过 mysqldump 导出可能我们都知道 mysqldump 可以将数据库中的数据以 INSERT 语句的形式生成相关备份文件,其实除了生成 INSERT 语句之外,mysqldump 还同样能实现上面"SELECT ... TO

    OUTFILE????FROM????..."所实现的功能,而且同时还会生成一个相关数据库结构对应的创建脚本 。

    如以下示例:

    root@sky:~# ls -l /tmp/mysqldump total 0 root@sky:~# mysqldump -uroot -T/tmp/mysqldump test test_outfile --fields-

    enclosed-by=\" --fields-terminated-by=, root@sky:~# ls -l /tmp/mysqldump total 8

    ????-rw-r--r--????1????root????root????1346????2008-10-14????22:18????test_outfile.sql

    ????-rw-rw-rw-????1????mysql????mysql????2521????2008-10-14????22:18????test_outfile.txt

    ????root@sky:~#????cat????/tmp/mysqldump/test_outfile.txt

    350021,21,"A","abcd"

    350022,22,"B","abcd"

    350023,23,"C","abcd"

    350024,24,"D","abcd"

    350025,25,"A","abcd" ...????...

    ????root@sky:~#????cat????/tmp/mysqldump/test_outfile.sql

    ????--????MySQL????dump????10.11

    --

    ????--????Host:????localhost????Database:????test

    --????-------------------------------------------------------????Server????version????5.0.51a-log

    ????/*!40101????SET????@OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;

    ????/*!40101????SET????@OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;

    ????/*!40101????SET????@OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;

    ????/*!40101????SET????NAMES????utf8????*/;

    ????/*!40103????SET????@OLD_TIME_ZONE=@@TIME_ZONE????*/;

    ????/*!40103????SET????TIME_ZONE=‘+00:00‘????*/;

    ????/*!40101????SET????@OLD_SQL_MODE=@@SQL_MODE, SQL_MODE=‘‘????*/;

    ????/*!40111????SET????@OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0????*/;

    --

    --????Table????structure????for????table????`test_outfile` --

    ????DROP????TABLE????IF????EXISTS????`test_outfile`;

    ????SET????@saved_cs_client????=????@@character_set_client;

    ????SET????character_set_client =????utf8;

    ????CREATE????TABLE????`test_outfile` (

    ????`id`????int(11)????NOT????NULL????default????‘0‘,

    ????`t_id`????int(11)????default????NULL,

    ????`a`????char(1)????default????NULL,

    ????`mid`????varchar(32)????default????NULL

    ????)????ENGINE=MyISAM DEFAULT????CHARSET=utf8;

    ????SET????character_set_client =????@saved_cs_client;

    ????/*!40103????SET????TIME_ZONE=@OLD_TIME_ZONE????*/;

    ????/*!40101????SET????SQL_MODE=@OLD_SQL_MODE */;

    ????/*!40101????SET????CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;

    ????/*!40101????SET????CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;

    /*!40101????SET????COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; /*!40111????SET????SQL_NOTES=@OLD_SQL_NOTES */;

    ????--????Dump????completed????on????2008-10-14????14:18:23

    这样的输出结构对我们做为备份来使用是非常合适的,当然如果一次有多个表需要被 dump,就会针对每个表都会生成两个相对应的文件。

    5.2.3 逻辑备份恢复方法

    仅仅有了备份还是不够啊,我们得知道如何去使用这些备份,现在我们就看看上面所做的逻辑备份的恢复方法:

    由于所有的备份数据都是以我们最初数据库结构的设计相关的形式所存储,所以逻辑备份的恢复也相对比较简单。当然,针对两种不同的逻辑备份形式,恢复方法也稍有区别。下面我们就分别针对这两种逻辑备份文件的恢复方法做一个简单的介绍。

    1. INSERT 语句文件的恢复:

    对于 INSERT 语句形式的备份文件的恢复是最简单的,我们仅仅只需要运行该备份文件中的所有(或者部分)SQL 命令即可。首先,如果需要做完全恢复,那么我们可以通过使用 "mysql < backup.sql"直接调用备份文件执行其中的所有命令,将数据完全恢复到备份时候的状态。如果已经使用 mysql 连接上了 MySQL,那么也可以通过在 mysql 中执行"source

    /path/backup.sql"或者"\.????/path/backup.sql"来进行恢复。

    1. 纯数据文本备份的恢复:

    如果是上面第二中形式的逻辑备份,恢复起来会稍微麻烦一点,需要一个表一个表通过相关命令来进行恢复,当然如果通过脚本来实现自动多表恢复也是比较方便的。恢复方法也有两个,一是通过 MySQL 的"LOAD????DATA????INFILE"命令来实现,另一种方法就是通过 MySQL 提供的使用工具 mysqlimport 来进行恢复。

    逻辑备份能做什么?不能做什么?

    在清楚了如何使用逻辑备份进行相应的恢复之后,我们需要知道我们可以利用这些逻辑备份做些什么。

    1. 通过逻辑备份,我们可以通过执行相关 SQL 或者命令将数据库中的相关数据完全恢复到备份时候所处的状态,而不影响不相关的数据;
    2. 通过全库的逻辑备份,我们可以在新的 MySQL 环境下完全重建出一个于备份时候完全一样的数据库,并且不受 MySQL 所处的平台类型限制;
    3. 通过特定条件的逻辑备份,我们可以将某些特定数据轻松迁移(或者同步)到其他的 MySQL 或者另外的数据库环境;
    4. 通过逻辑备份,我们可以仅仅恢复备份集中的部分数据而不需要全部恢复。

      在知道了逻辑备份能做什么之后,我们必须还要清楚他不能做什么,这样我们自己才能清楚的知道这样的一个备份能否满足自己的预期,是否确实是自己想要的。

        ????LOAD????DATA????INFILE????‘/tmp/test_outfile.txt‘????INTO????TABLE????test_outfile????FIELDS

        TERMINATED????BY????‘"‘????ENCLOSED????BY????‘,‘;

        后面的步骤就和备份文件为 INSERT 语句备份的恢复完全一样了,这里就不再累述。

        5.3 物理备份与恢复测试

        前面一节我们了解了如何使用 MySQL 的逻辑备份,并做了一个简单的逻辑备份恢复示例,在这一节我们再一起了解一些 MySQL 的物理备份。

        5.3.1 什么样的备份是数据库物理课备份

        在了解 MySQL 的物理备份之前,我们需要先了解一下,什么是数据库物理备份?既然是物理备份,那么肯定是和数据库的物理对象相对应的。就如同逻辑备份根据由我们根据业务逻辑所设计的数据库逻辑对象所做的备份一样,数据库的物理备份就是对数据库的物理对象所做的备份。数据库的物理对象主要由数据库的物理数据文件、日志文件以及配置文件等组成。在 MySQL 数据库中,除了 MySQL 系统共有的一些日志文件和系统表的数据文件之外,每一种存储引擎自己还会有不太一样的物理对象,在之前第一篇的"MySQL 物理文件组成"中我们已经有了一个基本的介绍,在下面我们将详细列出几种常用的存储引擎各自所对应的物理对象(物理文件),以便在后面大家能够清楚的知道各种存储引擎在做物理备份的时候到底哪些文件是需要备份的哪些又是不需要备份的。

        5.3.2 MySQL 物理备份所需文件

        MyISAM 存储引擎

        MyISAM 存储引擎的所有数据都存放在 MySQL 配置中所设定的"datadir"目录下。实际上不管我们使用的是 MyISAM 存储引擎还是其他任何存储引擎,每一个数据库都会在 "datadir"目录下有一个文件夹(包括系统信息的数据库 mysql 也是一样)。在各个数据库中每一个 MyISAM 存储引擎表都会有三个文件存在,分别为记录表结构元数据的".frm"文件,存储表数据的".MYD"文件,以及存储索引数据的".MYI"文件。由于 MyISAM 属于非事务性存储引擎,所以他没有自己的日志文件。所以 MyISAM 存储引擎的物理备份,除了备份 MySQL 系统的共有物理文件之外,就只需要备份上面的三种文件即可。

        Innodb 存储引擎

        Innodb 存储引擎属于事务性存储引擎,而且存放数据的位置也可能与 MyISAM 存储引擎有所不同,这主要取决于我们对 Innodb 的""相关配置所决定。决定 Innodb 存放数据位置的 配 置 为 " innodb_data_home_dir " 、 " innodb_data_file_path " 和 "innodb_log_group_home_dir"这三个目录位置指定参数,以及另外一个决定 Innodb 的表空间存储方式的参数"innodb_file_per_table"。前面三个参数指定了数据和日志文件的存放位置,最后一个参数决定 Innodb 是以共享表空间存放数据还是以独享表空间方式存储数据。这几个参数的相关使用说明我们已经在第一篇的"MySQL 存储引擎介绍"中做了相应的解释,在 MySQL 的官方手册中也有较为详细的说明,所以这里就不再累述了。

        ????如 果 我 们 使 用 了 共 享 表 空 间 的 存 储 方 式 , 那 么????Innodb????需 要 备 份 备 份

        "innodb_data_home_dir"和"innodb_data_file_path"参数所设定的所有数据文件,

        "datadir"中相应数据库目录下的所有 Innodb 存储引擎表的".frm"文件;

        而如果我们使用了独享表空间,那么我们除了备份上面共享表空间方式所需要备份的所有文件之外,我们还需要备份"datadir"中相应数据库目录下的所有".idb"文件,该文件中存放的才是独享表空间方式下 Innodb 存储引擎表的数据。可能在这里有人文,既然是使用独享表空间,那我们为什么还要备份共享表空间"才使用到"的数据文件呢?其实这是很多人的一个共性误区,以为使用独享表空间的时候 Innodb 的所有信息就都存放在 "datadir"所设定数据库目录下的".ibd"文件中。实际上并不是这样的,".ibd"文件中所存放的仅仅只是我们的表数据而已,大家都很清楚,Innodb 是事务性存储引擎,他是需要 undo 和 redo 信息的,而不管 Innodb 使用的是共享还是独享表空间的方式来存储数据,与事务相关的 undo 信息以及其他的一些元数据信息,都是存放在"innodb_data_home_dir" 和"innodb_data_file_path"这两个参数所设定的数据文件中的。所以要想 Innodb 的物理备 份 有 效 ,"innodb_data_home_dir"和"innodb_data_file_path"参数所设定的数据文件不管在什么情况下我们都必须备份。

        此外,除了上面所说的数据文件之外,Innodb 还有自己存放 redo 信息和相关事务信息的日志文件在"innodb_log_group_home_dir"参数所设定的位置。所以要想 Innodb 物理备份能够有效使用,我们还比需要备份"innodb_log_group_home_dir"参数所设定的位置的所有日志文件。

        NDB????Cluster 存储引擎

        NDB Cluster 存储引擎(其实也可以说是 MySQL Cluster)的物理备份需要备份的文件主要有一下三类:

          Cluster????提供了相应的命令来中断当前正在进行的备份操作,如下:

          1. 登录管理节点
          2. 执行????"ABORT????BACKUP????backup_id",命令中的????backup_id????即之前发起备份命令的时候所产生的备份号。
          3. 管理结带你上会用消息"放弃指示的备份 backup_id"确认放弃请求,注意,则时候其实并没有收到数据节点对请求的实际回应。
          4. 然后管理节点才会将中断备份的指令发送到所有数据节点上面,然后当各个数据节点都中断备份并删除了当前产生的备份文件之后,才会返回"备份 backup_id 因*

            **而放弃"。至此,中断备份操作完成。

          通过????NDB????Cluster????存储引擎自己的备份命令来进行备份之后,会将前面所提到的三种文件存放在参与备份的节点上面,且被存放在三个不同的文件中,类似如下:

          BACKUP-backup_id.node_id.ctl,内容包含相关的控制信息和元数据的控制文件。每个节点均会将相同的表定义(对于????Cluster????中的所有表)保存在自己的该文件中。

          BACKUP-backup_id-n.node_id.data,数据备份文件,被分成多个不同的片段来保存,在备份过程中,不同的节点将保存不同的备份数据所产生的片段,每个节点保存的文件都会有信息指明数据所属表的部分,且在备份片段文件最后还包含了最后的校验信息,以确保备份能够正确恢复。

          BACKUP-backup_id.node_id.log,事务日志备份文件中仅包含已提交事务的相关信息,且仅保存已在备份中保存的表上的事务,各个阶段所保存的日志信息也不一样,因为仅仅针对各节点所包含的数据记录相关的日志信息。

          上面的备份文件命名规则中,backup_id 是指备份号,不同的备份集会针对有一个不同的备份号,node_id 则是指明该备份文件属于哪个数据节点,而在数据文件的备份文件中的 n 则是指明片段号。

          5.3.4 各存储引擎常用物理备份恢复方法

          和之前逻辑备份一样,光有备份是没有意义的,还需要能够将备份有效的恢复才行。物理备份和逻辑备份相比最大的优势就是恢复速度快,因为主要是物理文件的拷贝,将备份文件拷贝到需要恢复的位置,然后进行简单的才做即可。

          MyISAM????存储引擎

          ????MyISAM????存储引擎由于其特性,物理备份的恢复也比较简单。

          如果是通过停机冷备份或者是在运行状态通过锁定写入操作后的备份集来恢复,仅仅只需要将该备份集直接通过操作系统的拷贝命令将相应的数据文件复制到对应位置来覆盖现有文件即可。

          如果是通过????mysqlhotcopy????软件来进行的在线热备份,而且相关的备份信息也记录进入了数据库中相应的表,其恢复操作可能会需要结合备份表信息来进行恢复。

          Innodb????存储引擎

          对于冷备份,Innodb????存储引擎进行恢复所需要的操作和其他存储引擎没有什么差别,同样是备份集文件(包括数据文件和日志文件)复制到相应的目录即可。但是对于通过其他备份软件所进行的备份,就需要根据备份软件本身的要求来进行了。比如通过????ibbackup????来进行的备份,同样也需要通过他来进行恢复才可以,具体的恢复方法请通过该软件的使用手册来进行,这里就不详细介绍了。

          NDB????Cluster????存储引擎

          对于停机冷备,恢复方法和其他存储引擎也没有太多区别,只不过有一点需要特别注意的就是恢复的时候必须要将备份集中文件恢复到对应的数据节点之少,否则无法正确完成恢复过程。

          而通过????NDB????Cluster????所提供的备份命令来生成的备份集,需要使用专用的备份恢复软件????ndb_restore????来进行。ndb_restore????软件将从备份集中读取出备份相关的控制信息,而且????ndb_restore????软件必须在单独的数据节点上面分别进行。所以当初备份进行过程中有多少数据节点,现在就需要运行多少次????ndb_restore。而且,首次通过????ndb_restore????来进行恢复的话,还必须恢复元数据,也就是会重建所有的数据库和表。

          5.5 备份策略的设计思路

          备份是否完整,能否满足要求,关键还是需要看所设计的备份策略是否合理,以及备份操作是否确实按照所设计的备份策略进行了。

          针对于不同的用途,所需要的备份类型是不一样的,所以需要的备份策略有各有不同。如为了应对本章最开始所描述的在线应用的数据丢失的问题,我们的备份就需要快速恢复,而且最好是仅仅需要增量恢复就能找回所需数据。对于这类需求,最好是有在线的,且部分延迟恢复的备用数据库。因为这样可以在最短时间内找回所需要的数据。甚至在某些硬件设备出现故障的时候,将备用库直接开发对外提供服务都可以。当然,在资源缺乏的情况下,可能难以找到足够的备用硬件设备来承担这个备份责任的时候,我们也可以通过物理备份来解决,毕竟物理备份的恢复速度要比逻辑备份的快很多。

          而对于那些非数据丢失的应用场景,大多数时候恢复时间的要求并不是太高,只要可以恢复出一个完整可用的数据库就可以了。所以不论是物理备份还是逻辑备份,影响都不大。

          从我个人经验来看,可以根据不同的需求不同的级别通过如下的几个思路来设计出合理的备份策略:

          1. 对于较为核心的在线应用系统,比需要有在线备用主机通过????MySQL????的复制进行相应的备份,复制线程可以一直开启,恢复线程可以每天恢复一次,尽量让备机的数据延后主机在一定的时间段之内。这个延后的时间多长合适主要是根据实际需求决定,一般来说延后一天是一个比较常规的做法。
          2. 对于重要级别稍微低一些的应用,恢复时间要求不是太高的话,为了节约硬件成本 ,不必要使用在线的备份主机来单独运行备用 MySQL,而是通过每一定的时间周期内进行一次物理全备份,同时每小时(或者其他合适的时间段)内将产生的二进制日志进行备份。这样虽然没有第一种备份方法恢复快,但是数据的丢失会比较少。恢复所需要的时间由全备周期长短所决定。
          3. 而对于恢复基本没有太多时间要求,但是不希望太多数据丢失的应用场景,则可以通过每一定时间周期内进行一次逻辑全备份,同时也备份相应的二进制日志。使用逻辑备份而不使用物理备份的原因是因为逻辑备份实现简单,可以完全在线联机完成,备份过程不会影响应用提供服务。
          4. 对于一些搭建临时数据库的备份应用场景,则仅仅只需要通过一个逻辑全备份即可满足需求,都不需要用二进制日志来进行恢复,因为这样的需求对数据并没有太苛刻的要求。

          上面的四种备份策略都还比较较粗糙,甚至不能算是一个备份策略。目的只是希望能给大家一个指定备份策略的思路。各位读者朋友可以根据这个思路根据实际的应用场景,指定出各种不同的备份策略。

          5.6 小结

          总的来说,MySQL????的备份与恢复都不是太复杂,方法也比较单一。姑且不说逻辑备份,对于物理备份来说,确实是还不够完善。缺少一个开源的比较好的在线热物理备份软件,一直是????MySQL????一个比较大的遗憾,也是所有????MySQL????使用者比较郁闷的事情。

          当然,没有开源的备份软件使用,非开源的商业软件也还是有的,如比较著名的 Zmanda 备份恢复软件,功能就比较全面,使用也不太复杂,在商业的 MySQL 备份恢复软件市场上有较高的占有率。而且,Zmanda 同时还提供社区版本的免费下载使用。

          不过,稍微让人有所安慰的是????MySQL????在实际应用场景中大多是有一台或者多台????Slave 机器来作为热备的。在需要进行备份的时候通过????Slave????来进行备份也不是太难,而且通过暂时停止????Slave????上面的????SQL????线程,即可让????Slave????机器停止所有数据写入操作,然后就可以进行在线进行备份操作了。所以即使买不起商用软件或者不太想买关系也不是太大。

热门排行

今日推荐

热门手游