16.7 备份恢复

对于任何数据库来说,备份都是非常重要的

数据库复制不能取代备份的作用

比如我们由于误操作,在主数据库上删除了一些数据,由于主从复制的时间很短,在发现时,从数据库上的数据可能也已经被删除了, 我们不能使用从数据库上的数据来恢复主数据库上的数据,只能通过备份进行误删除数据的恢复

1 备份的分类

1.1 按备份的结果来分

1.1.1 逻辑备份

其备份结果为SQL语句,适合于所有存储引擎,恢复时需要较多时间,逻辑备份时,对于MyISAM存储引擎是需要进行锁表操作的,通过使用的mysqldump就是一种逻辑备份工具

1.1.2 物理备份

是对数据库目录的拷贝,其备份结果的大小通常也与备份数据的数据目录大小相同,物理备份和恢复通常比逻辑备份要快,因为只需要对mysql数据目录拷贝即可,也正是因为这点,对于内存表只能备份其结构,无法备份数据(因为其数据存储在内存中,没有实际的物理数据文件)

物理备份的方式

进行物理备份,我们可以采用离线备份和在线备份的方式进行备份

  • 离线备份:需要对数据库进行停机,或对整个数据库进行锁定的情况下进行

  • 在线备份:需要使用第三方工具,如 XtraBackup

1.2 按备份的数据库的内容来分

1.2.1 全量备份

是对整个数据库的一个完整备份

1.2.2 增量备份

是在上次全量或增量备份的基础上,对更改过的数据进行的备份

注意:

Mysql官方提供的mysqldump命令并不支持增量备份

通常情况要使用mysqldump来进行增量备份的话,增量备份只能通过备份Mysql的二进制日志来实现

XtraBackup本身就提供了增量备份的功能,所以对于Innodb来说,使用XtraBackup进行备份更加安全高效

无论是使用XtraBackup还是Mysqldump 进行备份,要进行基于时间点的恢复时都需要利用Mysql的二进制日志,所以通常情况下我们需要对Mysql的二进制日志也进行备份

2 使用mysqldump进行备份

mysqldump 是mysql官方提供的逻辑备份工具,其备份结果是可读的SQL文件

mysqldump 支持多种语法

2.1 常用语法

2.1.1 对一个数据库下的一个或多个表进行备份

备份多个表时,table直接用空格进行分隔

2.1.2 对指定的多个数据库进行备份

2.1.3 对整个mysql实例下的所有数据库进行备份

2.2 常用参数

2.3 演示

2.3.1 创建备份用户

2.3.2 赋予用户备份权限

2.3.3 使用mysqldump进行全量备份

2.3.3.1 备份某个数据库

如果遇到以下问题

MySQL中二进制日志功能默认是关闭,去/etc/my.cnf 文件中加入下面配置,开启log_bin(数据库的操作日志)功能,然后重启mysql即可解决问题

之后使用 “systemctl start mysql” 重启服务器,报错

解决方法:

在设置 log-bin 的时候同时需要设置 server-id 变量,即在配置文件中添加:

然后再次重启即可

补充知识

再次执行之前的备份命令,即可成功被封mc_orderdb数据库下的所有表,我们可以查询一下备份的SQL文件中是否包含所有表

通过上面结果可以看出我们的几个表都在其中

2.3.3.2 备份某个数据库下的某个表

2.3.3.3 备份MySQL实例下的所有数据库

由于master-data的值设置为1,change master命令并没有被注释掉,如果我们使用这个命令进行恢复,change master命令就会被执行,在一些情况下可能会造成一些错误,所以建议使用时最好还是设置为2

可以通过下面的命令查看,备份文件中包含哪些数据库

2.3.4 使用-tab参数指定备份文件的位置

首先在/tmp 目录下建立一个mc_orderdb目录用来存放指定的备份文件,之所以使用在此目录下建立目录,是因为使用--tab参数时,用户必须对目标目录有可写权限,而tmp目录对任何用户都有可写权限

现在我们可以使用--tab参数指定备份路径

可以发现,报错了,其实我们在这之前还缺少一步,由于用户需要有写文件的权限,所以我们还需要对备份用户赋予file权限

我们再次执行上面的备份命令

可以很清楚地从提示看到是因为mysql服务启用了–secure-file-priv,所以才无法执行。 那么–secure-file-priv又是什么呢,应该如何解决才能是它可以备份呢? --secure-file-priv=name : Limit LOAD DATA, SELECT ... OUTFILE, and LOAD_FILE() to files within specified directory

可以看到secure-file-priv参数是用来限制LOAD DATA, SELECT … OUTFILE, and LOAD_FILE()传到哪个指定目录的。

当secure_file_priv的值为null ,表示限制mysqld 不允许导入|导出

当secure_file_priv的值为/tmp/ ,表示限制mysqld 的导入|导出只能发生在/tmp/目录下

当secure_file_priv的值没有具体值时,表示不对mysqld 的导入|导出做限制

查看数据库当前该参数的值

清楚地看到secure_file_priv 的值是NULL,说明此时限制导入导出的 所以应该改变该参数 可是查看了mysql.cnf中居然没有对这个参数进行设定,就说明这个参数默认便是null 所以再mysql.cnf中的[mysqld]加入secure_file_priv =

再重启mysql服务

然后再查一下此时参数的值

已经是我们要的结果 ,现在我们再次执行备份命令

结果还是权限被拒绝,无法写入,我们可以查询一下目录mc_orderdb的权限,

可以发现,是root用户建立的目录,我们需要修改其所属用户为mysql用户,然后再次执行备份命令

可以发现,修改成功后即可备份成功

进入该目录下会发现mc_orderdb数据库下的每个表都有两种文件,一种.sql结尾记录是表结构,一种是.txt结尾的表数据

2.3.5 mysqldump如何使用全备where参数

使用场景

假设我们要对订单id为1000到1050的主表进行修改,修改之前,我们需要先对数据进行备份,这里我们就可以使用where参数来完成此需求

执行命令进行备份

查看备份文件可以发现,订单id是从1001开始的

2.4 定义备份脚本

在日程工作中我们不可能一直手工备份,所以我们需要将备份进行脚本话,然后使用计划任务去执行脚本

2.4.1 脚本文件

2.4.2 执行脚本文件

可以看到结果已备份,可以使用crontab命令定时执行此脚本

3 如何恢复mysqldump备份的数据库

3.1 方法一

3.2 方法二

使用mysqldump备份时,恢复的速度完全取决于MySQL实例执行SQL的速度和服务器的IO性能,并且恢复过程是单线程的,所以对于非常大的数据集来说,要恢复的话可能需要很长的时间

备份恢复时,要先创建数据库

3.3 演示:

把刚才的全备数据恢复到bak数据库中

创建bak_orderdb数据库

将mc_orderdb备份的数据恢复到bak数据库中

检验恢复结果的正确性

3.3.1 模拟误操作并恢复数据

假设我们现在不小心删除了mc_orderdb下的order_master中的10条数据,我们现在需要通过刚刚恢复的备份数据库把这10条数据恢复回来

首先查出被误删的数据 SELECT a.* FROM bak_orderdb.order_master a LEFT JOIN mc_orderdb.order_master b ON a.order_id=b.order_id WHERE b.order_id IS NULL; 然后执行insert语句将查出的数据插入回去

完整语句为

执行结果:

对于一些静态型数据我们可以这样进行,但是对于一些时刻有数据在往表里写的数据还原,就不能使用这种方式了

对于生产环境中,时刻有数据写入的表如何进行数据恢复呢?

3.3.2 mysqldump单表备份恢复(使用了--tab参数备份的结果集)

需要进入mysql客户端中

先恢复表结构

再导入数据

3.4 如何进行指定时间点的恢复

进行某一时间点的数据恢复,恢复到误操作的时间

3.4.1 先决条件

具有指定时间点前的mysqldump的全备 具有全备到指定时间点的mysql二进制日志

3.4.2 演示

首先我们需要有个数据库的全备,此处我们对mc_orderdb 数据库进行全备

然后我们模拟一下生产环境中对数据库的操作,这样才能看到时间点恢复的效果

我们到mc_orderdb数据库中新建一个统计表 t, uid列是用户id,cnt 是用户的总消费金额,将统计结果插入表t中后,模拟误操作,删除表t中的100行数据

先恢复一个最近的全备,进行全量数据恢复

然后查看mc_orderdb.sql文件中change master命令中

在进行这个全备时Mysql二进制日志的文件名(MASTER_LOG_FILE),以及时间点(MASTER_LOG_POS)

此处文件名为mysql-bin.000001,日志时间点为154;

下面我们要恢复这个时间点(154)之后到第一次删除数据之前的数据

要找到这个时间点(154)之后到第一次删除数据之前的数据

查看二进制日志,进行分析

从中可以看到刚刚的二进制日志中的第一个DELETE,在它之前的日志结束点为84620

所以我们需要恢复的是154 到84620 之间,且数据库为mc_orderdb ,日志所在文件名 为mysql-bin.000001的数据

我们通过mysqlbinlog 将这些数据导出来

将数据导入恢复

4 实时二进制日志备份

Mysql5.6版本之后,可以实时备份Binlog(二进制日志)

要使用这个功能,我们需要进行以下配置 首先新建一个用户,这个用户要有replication slave 权限

建立一个存储备份的二进制日志文件的目录

最后在这个目录下,执行以下命令,就可以实时的进行二进制日志的备份了

raw:代表这个命令是输出的是raw格式的二进制日志 read-from-remote-server: 从mysql服务器上读取这个日志 stop-never:备份的这个进程会持续在后台运行 最后的是指定要备份的二进制文件的名称

备份的二进制文件的名称,必须为最新的二进制备份文件

此命令执行后这个终端会一直执行这个命令 现在打开另外一个终端,进入备份的目录进行查看

可以看到日志已经备份成功 进入mysql命令行,刷新日志

现在有两个日志,我们再回到备份目录进行查看

可以看到最新的日志也已实时备份

5 xtrabackup

5.1 xtrabackup介绍

xtrabackup 物理备份工具,用于在线备份innodb存储引擎的表

在所有表全是innodb存储引擎表的情况下: xtrabackup 可以保证在备份过程中,不影响表的读写操作 在最初的时候,xtrabackup 本身只支持对innodb存储引擎表的备份,且只会备份数据文件,不会备份表的结构 innobackupex 是对xtrabackup 的插件,提供了备份表结构及其他配置信息的功能,并支持MyISAM表的备份,但也会锁表

因为在当前的mysql版本下,还有一些系统表使用的是MyISAM存储引擎,所以一般情况下使用的是innobackupex 脚本进行备份的

5.2 安装xtrabackup

下载地址:https://www.percona.com/downloads/XtraBackup/ 可以在该网址下载源码包或者rpm包

5.3 利用innobackupex 进行全备

当看到completed OK!代表备份已完成

和mysqldump单线程备份不同,我们可以通过parallel参数指定备份的线程数 /home/db_backup/ 是我们指定的备份文件的存储目录

xtrabackup 会已当前时间在目标目录中生成一个子目录用来存放当前的备份文件

我们进入目录中查看一下

  • xtrabackup_checkpoints :备份类型(如完全或增量)、备份状态(如是否已经为prepared状态)和LSN(日志序列号)范围信息;

    每个InnoDB页(通常为16k大小)都会包含一个日志序列号,即LSN。LSN是整个数据库系统的系统版本号,每个页面相关的LSN能够表明此页面最近是如何发生改变的。

  • xtrabackup_binlog_info: mysql服务器当前正在使用的二进制日志文件及至备份这一刻为止二进制日志事件的位置。

  • xtrabackup_info: xtrabackup工具在备份时记录的使用工具及数据库信息

  • backup-my.cnf —— 备份命令用到的配置选项信息;

  • xtrabackup_logfile —— xtrabackup记录innodb事物日志的信息

与原数据文件目录相比,少了ib_logfile0等日志文件

xtrabackup_binlog_info 比较重要,其中记录了备份的日志名和日志点,相当于mysqldump中设置master-data参数的作用

如果我们不想以时间戳的形式自动生成子目录,我们可以通过指定--no-timestamp参数来实现

5.4 利用innobackupex 进行全备的恢复

准备完全备份

innobakupex命令的--apply-log选项可用于实现上述功能。如下面的命令:

进行数据库恢复之前,我们必须把备份中产生的备份集 进行应用,此处我们使用的是备份文件的目录伪2019-01-10

可以发现,使用了上面的命令后,备份集中多出了之前缺少的ib_logfile0等文件。

​ 在实现“准备”的过程中,innobackupex通常还可以使用--use-memory选项来指定其可以使用的内存的大小,默认通常为100M。如果有足够的内存可用,可以多划分一些内存给prepare的过程,以提高其完成速度。

使用xtrabackup进行数据库恢复时,我们必须对数据库实例进行重启 先停用mysql服务

然后将原数据库文件所在的文件夹重命名为data_bak,然后将此时的 2019-01-10文件夹移动到data_bak所在的文件夹,并重命名为data,即覆盖了原来的文件

然后 chown -R mysql:mysql data 对文件夹修改所属用户

最后重启mysql服务即可

5.5 利用innobackupex 进行增量备份

incremental :表示我们要进行的是一个全备, 指定全备的目录 incremental-basedir :指定增量备份所依赖的数据基础的备份目录,这个增量备份所依赖的上一个全备

演示

先进行全备

在 /home/db_backup 目录下生产了一个新的全备子目录 2019-01-10_16-19-37

再依赖上个全量备份进行增量备份

此时在 /home/db_backup 目录下生产了一个增量备分的子目录2019-01-10_16-22-09 增量备份会把自上一个全备后的数据变更记录下来

然后再进行一次增量备份,此时的命令和前面基本相同,只是所基于的增量备份的数据目录要变成上次增量备份生成的目录

此时,第二次增量备份的生成的目录名为2019-01-10_16-24-09

5.6 利用innobackupex 进行增量恢复

我们要循环的在多次增量备份中应用上面步骤

所有增量备份的都应有了上面的命令后,就可以像全备一样,在全备目录上再进行崩溃恢复的过程

最后和全备一样,要用全备目录替换mysql数据库目录

演示

下面演示只恢复到第一次备份

5.7 备份压缩和流

Stream模式下,Xtrabackup的STDOUT可以指定tar或者xbstream格式输出。 ' 流允许,其他程序过滤备份输出,提供更大的灵活存储backup。 使用流特性,需要指--stream选项 $ innobackupex --stream=tar /tmp innobackupex会用子程序启动xtrabackup --log-stream 定向到临时文件,然后使用tar把所有数据文件steam到STDOUT。 当压缩启动,xtrabackup压缩所有输出数据,但是元数据和非innodb文件不能被压缩。现在唯一支持的压缩算法是quicklz。会生产qpress归档格式的文件。

演示

使用tar备份

使用tar备份到其他服务器: 依赖密钥传输数据

提取tar流,需要加i参数,否则容易数据丢失

也可以压缩流:

xtrabckup还有部分备份和窄备份功能 略

参考文章:

https://www.cnblogs.com/huchong/p/10238515.html#_label1

https://www.linuxidc.com/Linux/2019-01/156363.htm

Last updated

Was this helpful?