MySql(四):备份与恢复

一、数据库备份使用场景

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

a、数据丢失应用场景

1、人为操作失误造成某些数据被误操作;
2、软件BUG 造成数据部分或者全部丢失;
3、硬件故障造成数据库数据部分或全部丢失;
4、安全漏洞被入侵数据被恶意破坏;

b、非数据丢失应用场景

5、特殊应用场景下基于时间点的数据恢复;
6、开发测试环境数据库搭建;
7、相同数据库的新环境搭建;
8、数据库或者数据迁移;

没有哪一种数据库备份能够解决所有以上列举的几种常见应用场景。

二、逻辑备份

1.逻辑备份定义

数据库逻辑备份就是备份软件按照我们最初所设计的逻辑关系,以数据库的逻辑结构对象为单位,将数据库中的数据按照预定义的逻辑关联格式一条一条生成相关的文本文件,以
达到备份的目的。

2.常用的逻辑备份

逻辑备份可以说是最简单,也是目前中小型系统最常使用的备份方式。在MySQL 中我们常用的逻辑备份主要就是两种,一种是将数据生成可以完全重现当前数据库中数据的INSERT 语句,另外一种就是将数据通过逻辑备份软件,将我们数据库表数据以特定分隔符进行分隔后记录在文本文件中

①生成INSERT 语句备份

在MySQL 数据库中,我们一般都是通过MySQL 数据库软件自带工具程序中的mysqldump来实现声称INSERT 语句的逻辑备份文件。

具体mysqldump如何使用,见互联网,这里为了确保系统的高可用,mysqldump备份会遇到的一些问题。

我们知道在系统正常运行过程中,很可能会不断有数据变更的请求正在执行,这样就可能造成在mysqldump 备份出来的数据不一致。也就是说备份数据很可能不是同一个时间点的数据,而且甚至可能都没办法满足完整性约束。这样的备份集对于有些系统来说可能并没有太大问题,但是对于有些对数据的一致性和完整性要求比较严格系统来说问题就大了,就是一个完全无效的备份集

对于如此场景,我们该如何做?我们知道,想数据库中的数据一致,那么只有两种情况下可以做到

  1. 第一、同一时刻取出所有数据;
  2. 第二、数据库中的数据处于静止状态。

对于第一种情况,大家肯定会想,这可能吗?不管如何,只要有两个以上的表,就算我们如何写程序,都不可能昨晚完全一致的取数时间点啊。是的,我们确实无法通过常规方法
让取数的时间点完全一致,但是大家不要忘记,在同一个事务中,数据库是可以做到所读取的数据是处于同一个时间点的。所以,对于事务支持的存储引擎,如Innodb 或者BDB 等,我们就可以通过控制将整个备份过程控制在同一个事务中,来达到备份数据的一致性和完整性,而且mysqldump 程序也给我们提供了相关的参数选项来支持该功能,就是通过“--single-transaction”选项,可以不影响数据库的任何正常服务。

对于第二种情况我想大家首先想到的肯定是将需要备份的表锁定,只允许读取而不允许写入。是的,我们确实只能这么做。我们只能通过一个折衷的处理方式,让数据库在备份过
程中仅提供数据的查询服务,锁定写入的服务,来使数据暂时处于一个一致的不会被修改的状态,等mysqldump 完成备份后再取消写入锁定,重新开始提供完整的服务。mysqldump 程序自己也提供了相关选项如“--lock-tables”和“--lock-all-tables”,在执行之前会锁定表,执行结束后自动释放锁定。这里有一点需要注意的就是,“--lock-tables”并不是一
次性将需要dump 的所有表锁定,而是每次仅仅锁定一个数据库的表,如果你需要dump 的表分别在多个不同的数据库中,一定要使用“--lock-all-tables”才能确保数据的一致完整

当通过mysqldump 生成INSERT 语句的逻辑备份文件的时候,有一个非常有用的选项可以供我们使用,那就是“--master-data[=value]”。当添加了“--master-data=1”的时候,mysqldump 会将当前MySQL 使用到binlog 日志的名称和位置记录到dump 文件中,并且是被以CHANGE_MASTER 语句的形式记录,如果仅仅只是使用“--master-data”或者“--masterdata=2”,则CHANGE_MASTER 语句会以注释的形式存在。这个选项在实施slave 的在线搭建的时候是非常有用的,即使不是进行在线搭建slave,也可以在某些情况下做恢复的过程中通过备份的binlog 做进一步恢复操作。

在某些场景下,我们可能只是为了将某些特殊的数据导出到其他数据库中,而又不希望通过先建临时表的方式来实现,我们还可以在通过mysqldump 程序的“where='wherecondition'”来实现,但只能在仅dump 一个表的情况下使用。

其实除了以上一些使用诀窍之外,mysqldump 还提供了其他很多有用的选项供大家在不同的场景下只用,如通过“--no-data”仅仅dump 数据库结构创建脚本,通过“--no-createinfo”
去掉dump 文件中创建表结构的命令等等。

②生成特定格式的纯文本备份数据文件备份

将数据库中的数据以特定分隔字符将数据分隔记录在文本文件中,这样的备份数据与INSERT 命令文件相比,所需要使用的存储空间更小,数据格式更加清晰明确,编辑方便。但是缺点是在同一个备份文件中不能存在多个表的备份数据,没有数据库结构的重建命令。对于备份集需要多个文件,对我们产生的影响无非就是文件多了维护和恢复成本增加,但这些基本上都可以通过编写一些简单的脚本来实现。

a.通过执行SELECT ... TO OUTFILE FROM ...命令来实现。

在MySQL 中提供了一种SELECT 语法,专供用户通过SQL 语句将某些特定数据以指定格式输出到文本文件中,同时也提供了实用工具和相关的命令可以方便的将导出文件原样再导
入到数据库中。正不正是我们做备份所需要的么?

该命令有几个需要注意的参数如下:

实现字符转义功能的“FIELDS ESCAPED BY ['name']” 将SQL 语句中需要转义的字符进行转义;
可以将字段的内容“包装”起来的“FIELDS [OPTIONALLY] ENCLOSED BY 'name'”,如果不使用“OPTIONALLY”则包括数字类型的所有类型数据都会被“包装”,使用“OPTIONALLY”
之后,则数字类型的数据不会被指定字符“包装”。
通过"FIELDS TERMINATED BY"可以设定每两个字段之间的分隔符;
而通过“LINES TERMINATED BY”则会告诉MySQL 输出文件在每条记录结束的时候需要添加什么字符。

示例:

 1 root@localhost : test 10:02:02> SELECT * INTO OUTFILE '/tmp/dump.text'
 2 -> FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
 3 -> LINES TERMINATED BY '\n'
 4 -> FROM test_outfile limit 100;
 5 Query OK, 100 rows affected (0.00 sec)
 6 root@localhost : test 10:02:11> exit
 7 Bye
 8 root@sky:/tmp# cat dump.text
 9 350021,21,"A","abcd"
10 350022,22,"B","abcd"
11 350023,23,"C","abcd"
12 350024,24,"D","abcd"
13 350025,25,"A","abcd"
14 ... ...

b.通过mysqldump 导出

示例:

root@sky:~# ls -l /tmp/mysqldump
total 0
root@sky:~# mysqldump -uroot -T/tmp/mysqldump test test_outfile --fieldsenclosed-
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

3.逻辑备份恢复方法

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

1、INSERT 语句文件的恢复:

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

2、纯数据文本备份的恢复:

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

4.逻辑备份优缺点总结

优点:

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

缺点:

1、逻辑备份无法让数据恢复到备份时刻以外的任何一个时刻;

三、物理备份

1.什么是数据库物理备份?

既然是物理备份,那么肯定是和数据库的物理对象相对应的。就如同逻辑备份根据由我们根据业务逻辑所设计的数据库逻辑对象所做的备份一样,数据库的物理备份就是对数据库的物理对象所做的备份。

数据库的物理对象主要由数据库的物理数据文件日志文件以及配置文件等组成。在MySQL 数据库中,除了MySQL 系统共有的一些日志文件和系统表的数据文件之外,每一种存
储引擎自己还会有不太一样的物理对象。

2.MySQL物理备份所需文件

MyISAM 存储引擎:“datadir”目录下,记录表结构元数据的“.frm”文件,存储表数据的“.MYD”文件,以及存储索引数据的“.MYI”文件。备份这三个文件即可。

Innodb 存储引擎:它的文件由相关配置决定,决定Innodb 存放数据位置的配置为“ innodb_data_home_dir ” 、“ innodb_data_file_path ” 和“innodb_log_group_home_dir”这三个目录位置指定参数,以及另外一个决定Innodb 的表空间存储方式的参数“innodb_file_per_table”。

前面三个参数指定了数据和日志文件的存放位置,最后一个参数决定Innodb 是以共享表空间存放数据还是以独享表空间方式存储数据。

共享表空间的存储方式,Innodb 需要备份备份“innodb_data_home_dir”和“innodb_data_file_path”参数所设定的所有数据文件,“datadir”中相应数据库目录下的所有Innodb 存储引擎表的“.frm”文件;

独享表空间的存储方式,那么我们除了备份上面共享表空间方式所需要备份的所有文件之外,我们还需要备份“datadir”中相应数据库目录下的所有“.idb”文件,该文件中存放的才是独享表空间方式下Innodb 存储引擎表的数据。

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

3.各存储引擎的热物理备份方法

由于冷物理备份比较简单,直接copy文件就可以了,但是实际环境中很少有数据库可以停下来让我们冷备份的情况,所以这里只介绍热物理备份

a.MyISAM 存储引擎

至少保证数据库在备份时候的数据是处于某一个时间点的,这样就要求我们必须做到在备份MyISAM 数据库的物理文件的时候让MyISAM 存储引擎停止写操作,仅仅提供读服务,其根本实质就是给数据库表加锁来阻止写操作。

方法1:MySQL 自己提供了一个使用程序mysqlhotcopy,这个程序就是专门用来备份MyISAM 存储引擎的。基本用法如下:

mysqlhotcopy db_name[./table_regex/] [new_db_name | directory]

从上面的基本使用方法我们可以看到,mysqlhotcopy 除了可以备份整个数据库,指定的某个表,还可以通过正则表达式来匹配某些表名来针对性的备份某些表。备份结果就是指
定数据库的文件夹下包括所有指定的表的相应物理文件。

方法2:通过登录数据库中手工加锁,然后再通过操作系统的命令来复制相关文件执行热物理备份,且在完成文件copy 之前,不能退出加锁的session(因为退出会自动解锁),如下:

root@localhost : test 08:36:35> FLUSH TABLES WITH READ LOCK;
Query OK, 0 rows affected (0.00 sec)

不退出mysql,在新的终端下做如下备份:

mysql@sky:/data/mysql/mydata$ cp -R test /tmp/backup/test
mysql@sky:/data/mysql/mydata$ ls -l /tmp/backup/
total 4
drwxr-xr-x 2 mysql mysql 4096 2008-10-19 21:57 test
mysql@sky:/data/mysql/mydata$ ls -l /tmp/backup/test
total 39268
-rw-r----- 1 mysql mysql 8658 2008-10-19 21:57 hotcopy_his.frm
-rw-r----- 1 mysql mysql 36 2008-10-19 21:57 hotcopy_his.MYD
-rw-r----- 1 mysql mysql 1024 2008-10-19 21:57 hotcopy_his.MYI
-rw-r----- 1 mysql mysql 8586 2008-10-19 21:57 memo_test.frm
... ...
-rw-rw---- 1 mysql mysql 8554 2008-10-19 22:01 test_csv.frm
-rw-rw---- 1 mysql mysql 0 2008-10-19 22:01 test_csv.MYD
-rw-rw---- 1 mysql mysql 1024 2008-10-19 22:01 test_csv.MYI
-rw-r----- 1 mysql mysql 8638 2008-10-19 21:57 test_myisam.frm
-rw-r----- 1 mysql mysql 20999600 2008-10-19 21:57 test_myisam.MYD
-rw-r----- 1 mysql mysql 10792960 2008-10-19 21:57 test_myisam.MYI
-rw-r----- 1 mysql mysql 8638 2008-10-19 21:57 test_outfile.frm
-rw-r----- 1 mysql mysql 2400 2008-10-19 21:57 test_outfile.MYD
-rw-r----- 1 mysql mysql 1024 2008-10-19 21:57 test_outfile.MYI
... ...

然后再在之前的执行锁定命令的session 中解锁

root@localhost : test 10:00:57> unlock tables;
Query OK, 0 rows affected (0.00 sec)

b.Innodb 存储引擎

Innodb 存储引擎由于是事务性存储引擎,有redo 日志和相关的undo 信息,而且对数据的一致性和完整性的要求也比MyISAM 要严格很多,所以Innodb 的在线(热)物理备份要
比MyISAM 复杂很多,一般很难简单的通过几个手工命令来完成,大都是通过专门的Innodb在线物理备份软件来完成。

Innodb 存储引擎的开发者(Innobase 公司)开发了一款名为ibbackup 的商业备份软件,专门实现Innodb 存储引擎数据的在线物理备份功能。该软件可以在MySQL 在线运行的状态下,对数据库中使用Innodb 存储引擎的表进行备份,不过仅限于使用Innodb 存储引擎的表。

4.各存储引擎常用物理备份的恢复方法

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

a.MyISAM存储引擎

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

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

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

b.InnoDB存储引擎

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

四、备份策略的设计思路

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

针对不同的用途,所需要的备份类型是不一样的,备份策略也各有不同。

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

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

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

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

热备份

Myisam  ----->  mysqlhotcopy

InnoDB  ----->  Xtrabackup

全量备份

增量备份

差异备份

mysqldump全量备份+mysqlbinlog二进制日志增量备份

mysqldump+系统计划任务定时备份MySql数据

Xtrabackup备份、还原、恢复Mysql操作大全

Centos 6.9 安装xtrabackup-2.4.8 通用包,yum安装,全量备份,增量备份

linux下利用shell脚本和mysqldump热备份和恢复mysql

MySql在生产环境中是用mysqldump还是xtrabackup备份和恢复数据

 

posted @ 2018-03-31 13:54  夏威夷8080  阅读(250)  评论(0编辑  收藏  举报