数据丢失的原因:

ü 程序错误、人为操作错误、运算错误

ü 磁盘故障、灾难(如火灾、地震)和盗窃等

数据库备份的类型:

从物理和逻辑角度看,数据库备份可以分为物理备份和逻辑备份。

物理备份又分为冷备份、热备份和温备份。

Ø 冷备份:在数据库关闭状态下进行备份操作

Ø 热备份:在数据库处于运行状态下进行备份操作,此方法依赖数据库的日志文件

Ø 温备份:数据库锁定表格(不可写但可读)的状态下进行备份操作

逻辑备份:是对数据库逻辑组件(如表等数据库对象)的备份。

从数据库备份策略角度看,数据库备份可以分为,完全备份,差异备份和增量备份

Ø 完全备份:每次都对整个数据库备份,是差异备份和增量备份的基础,缺点是会占用大量的磁盘空间,备份时间也很长

Ø 差异备份:备份从上次完整备份后修改过的所有文件,缺点是备份的数据量会越来越大,优点是恢复的时候只恢复上次的完整备份和最近一次的差异备份就好了

Ø 增量备份:只备份完整备份后或者增量备份后被修改的文件,优点是备份的数据量小,占用空间小,备份的速度快。缺点是在恢复的时候要从完整备份开始和增量备份的结束依次恢复,如果某次的备份损坏,将导致数据丢失

数据库完整备份

1. 物理冷备份与恢复

①物理冷备份一般使用的是tar工具打包数据库文件,在备份前需要先stop停掉数据库服务

[root@123 /]# systemctl stop mysqld                                                //停掉数据库服务
[root@123 /]# tar czvf /backup/mysql_$(date +%F).tar.gz /usr/local/mysql/        //备份整个数据库

②恢复数据库

[root@123 backup]# tar xzvf mysql_2019-01-13.tar.gz                      //解压备份的tar包
[root@123 backup]# cp -a usr/local/mysql/data /usr/local/mysql/        //将备份的date目录复制到mysql目录下

③重启mysqld服务,验证恢复效果

 

2. 使用mysqldump工具备份与恢复

该命令备份与恢复时不需要关闭数据库的服务,通过该命令可以将指定的库、表或全部的库导出为sql脚本

①备份数据库

[root@123 backup]# mysqldump -uroot -p --databases log > log.sql        //备份指定数据库log,导出为log.sql
[root@123 backup]# mysqldump -uroot -p log biao1 biao2 > biao12.sql        //备份log数据库中的biao1和biao2表
[root@123 backup]# mysqldump -uroot -p --all-databases > all.sql        //备份所有的数据库

②恢复数据库

注意:当备份文件中只有表备份的时候,恢复时需要指定一个现有的数据库用来存放恢复的数据表

[root@iZtmm4mufhb0rgZ backup]# mysql -uroot -p < log.sql         //恢复指定数据库备份文件
[root@iZtmm4mufhb0rgZ backup]# mysql -u root -p < all.sql         //恢复所有数据库备份文件
[root@iZtmm4mufhb0rgZ backup]# mysql -u root -p test < biao12.sql //恢复数据表备份文件

数据库增量备份

Mysql没有提供直接的增量备份方法,我们可以使用mysql提供的二进制日志间接的实现增量备份。使用增量备份前首先需要开启数据库的二进制日志功能,二进制日志文件扩展名是6位数字,如mysql-bin.000001

[root@nnv5 backup]# vim /etc/my.cnf   //编辑mysql配置文件
---------------------------------添加以下内容----------------------------------
log-bin=/usr/local/mysql/mysql-bin   //开启mysql二进制文件支持然后重启mysqld服务

Mysql增量恢复

常用的增量恢复有三种:一般恢复、基于位置恢复和基于时间恢复

一般恢复:将所有备份的二进制日志内容全部恢复

一般恢复语法:
mysqlbinlog --no-defaults 增量备份文件名 | mysql -u用户名 -p

基于位置恢复:将数据恢复到指定位置或指定开始恢复位置

基于位置恢复语法:
格式一:恢复到指定位置
mysqlbinlog --stop-position='操作id' 二进制文件名 | mysql -u用户名 -p
格式二:从指定位置开始恢复
mysqlbinlog --start-postion='操作id' 二进制文件名 | mysql -u用户名 -p

基于时间点恢复:跳过某个发生错误的时间点实现数据恢复

基于时间恢复语法:
格式一:从日志开头截止到某个时间点的恢复
mysqlbinlog --no-defaults --stop-datetime='年-月-日 小时:分钟:秒' 二进制日志 | mysql -u用户名 -p
格式二:从某个时间点到日志的结尾
mysqlbinlog --no-defaults --start-datetime='年-月-日 小时:分钟:秒' 二进制日志 | mysql -u用户名 -p
格式三:从某个时间点到某个时间点
mysqlbinlog --no-defaults --start-datetime='年-月-日 小时:分钟:秒' --stop-datetime='年-月-日 小时:分钟:秒' 二进制日志 | mysql -u用户名 -p

增量备份恢复案例:

² 一般恢复案例

①编辑配置文件,开启二进制日志的功能

[root@nnv5 ~]# vim /etc/my.cnf                        //编辑数据库配置文件
----------------添加以下参数-----------------------
log-bin=/usr/local/mysql/mysql-bin                   //开启二进制日志功能
 
[root@nnv5 ~]# systemctl restart mysqld                   //重启mysql服务
[root@nnv5 ~]# ls /usr/local/mysql/ | grep mysql-bin         //查看二进制日志文件

②登录数据库,创建一个数据库,在数据库中创建一个表并录入张三和李四的信息

[root@nnv5 ~]# mysql -uroot                                //登录数据库
mysql> create database client;                            //创建一个数据库名为client
mysql> use client;     //切换到client数据库
mysql> create table xinxi(××× char(20),姓名 char(20),性别 char(20),用户id char(20),资费 char(20));      //创建一个表设置字段
mysql> insert xinxi values ('000006','张三','男','016','61');             //在表中插入张三的信息
mysql> insert xinxi values ('000007','李四','男','017','91');             //在表中插入李四的信息

③为了验证二进制日志的增量恢复功能,在插入两条数据后对client数据库进行一次完整的备份,然后生成新的二进制日志文件

[root@nnv5 ~]# mkdir /mysql_bak           //创建完整备份存放的目录
[root@nnv5 ~]# mysqldump -uroot -p --databases client > /mysql_bak/client.sql    //将client数据库完整备份保存到mysql_bak目录
[root@nnv5 mysql_bak]# mysqladmin -uroot -p flush-logs                 //生成新的二进制日志文件
[root@nnv5 ~]# ls /usr/local/mysql/ | grep mysql-bin                 //查看二进制日志文件

④继续插入新的用户数据并刷新二进制日志文件进行增量备份,这样在完整备份的基础上新增加的操作备份插入王五和赵六的信息保存在000002二进制文件中

mysql> insert xinxi values ('000008','王五','女','018','23');         //在表中继续插入王五的信息
mysql> insert xinxi values ('000009','赵六','男','019','37');         //在表中继续插入赵六的信息
[root@nnv5 mysql_bak]#  mysqladmin -uroot -p flush-logs             //生成新的二进制文件
[root@nnv5 mysql_bak]# ls /usr/local/mysql/ | grep mysql-bin             //查看二进制日志文件

⑤模拟误操作,把xinxi这个数据表删除

mysql> drop table xinxi;    //删除xinxi这个表
mysql> select * from client.xinxi;    //查看表是否还存在

⑥恢复数据表信息,先进行完整备份恢复,然后在进行增量备份恢复

完整备份恢复

[root@nnv5 mysql_bak]# mysql -uroot -p < /mysql_bak/client.sql //恢复完整备份
mysql> select * from client.xinxi;   //查看表信息只有张三和李四的信息

增量备份一般恢复:在插入王五和赵六信息后重新生成了二进制文件,名为000002,因为这个二进制文件中保存了王五和赵六的信息

[root@nnv5 mysql_bak]# mysqlbinlog --no-defaults /usr/local/mysql/mysql-bin.000002 | mysql -uroot -p     //恢复000002二进制文件中的所有数据
mysql> select * from client.xinxi;   //查看表王五和赵六信息也恢复了

² 基于位置恢复

由于之前已经做过备份,就接前面的实验接着操作模拟故障与数据恢复

①模拟误操作,将xinxi表删除

mysql> drop table xinxi;    //删除xinxi这个表
mysql> select * from client.xinxi;    //查看表是否还存在

②完整备份恢复

[root@nnv5 mysql_bak]# mysql -uroot -p < /mysql_bak/client.sql //恢复完整备份
mysql> select * from client.xinxi;   //查看表信息只有张三和李四的信息

③要基于位置或者时间恢复数据,必须先查看二进制文件的内容获取到要恢复到的操作id或者要恢复到的时间点,可以使用“mysqlbinlog --no-defaults 二进制文件”查看二进制文件的具体内容

[root@nnv5 mysql_bak]# mysqlbinlog --no-defaults /usr/local/mysql/mysql-bin.000002
//查看000002二进制日志文件的内容
---------------------------------------------------------------------------------------------------------
# at 203
#181214  0:43:07 server id 1  end_log_pos 337 CRC32 0x4209f33e Query thread_id=2 exec_time=0 error_code=0
use `client`/*!*/;
SET TIMESTAMP=1544719387/*!*/;
insert xinxi values ('000008','王五','女','018','23')
/*!*/;
# at 337
#181214  0:43:07 server id 1  end_log_pos 368 CRC32 0xf4cb4c7d Xid = 38
COMMIT/*!*/;
# at 368
#181214  0:43:15 server id 1  end_log_pos 451 CRC32 0xa428e268 Query thread_id=2 exec_time=0 error_code=0
SET TIMESTAMP=1544719395/*!*/;
BEGIN
/*!*/;
# at 451
#181214  0:43:15 server id 1  end_log_pos 585 CRC32 0xc3e48c8c Query thread_id=2 exec_time=0 error_code=0
SET TIMESTAMP=1544719395/*!*/;
insert xinxi values ('000009','赵六','男','019','37')
/*!*/;
# at 585
#181214  0:43:15 server id 1  end_log_pos 616 CRC32 0xf05f2902 Xid = 39
COMMIT/*!*/;
# at 616
#181214  0:45:59 server id 1  end_log_pos 663 CRC32 0xb3cc49ad Rotate to mysql-bin.000003  pos: 4
DELIMITER ;
# End of log file
ROLLBACK /* added by mysqlbinlog */;
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;

④通过查看二进制文件内容可以看到每个操作前都有一个id或者时间点,例如在ID451之前插入了王五的信息

格式一:例如执行下面操作可以只将数据恢复到ID451,也就是说只恢复王五的信息,赵六的信息不恢复

[root@nnv5 mysql_bak]# mysqlbinlog --no-defaults --stop-position='451' /usr/local/mysql/mysql-bin.000002 | mysql -uroot -p   //恢复操作ID451之前的所有数据
mysql> mysql> select * from xinxi;  //查看xinxi表发现王五信息已经恢复了

格式二:如果执行下面操作是从ID451开始进行恢复,也就是说恢复id451之后的所有的数据,因此只会恢复赵六的数据,王五的数据就跳过了

[root@nnv5 mysql_bak]# mysqlbinlog --no-defaults --start-position='451' /usr/local/mysql/mysql-bin.000002 | mysql -uroot -p  //恢复操作ID451之后的所有数据
mysql> mysql> select * from xinxi;  //查看xinxi表发现王五信息已经恢复了

² 基于时间点恢复

由于之前已经做过备份,就接前面的实验接着操作模拟故障与数据恢复

①模拟误操作,将xinxi表删除

mysql> drop table xinxi;    //删除xinxi这个表
mysql> select * from client.xinxi;    //查看表是否还存在

②完整备份恢复

[root@nnv5 mysql_bak]# mysql -uroot -p < /mysql_bak/client.sql //恢复完整备份
mysql> select * from client.xinxi;   //查看表信息只有张三和李四的信息

③使用“mysqlbinlog --no-defaults 二进制文件”查看二进制文件时间点

[root@nnv5 mysql_bak]# mysqlbinlog --no-defaults /usr/local/mysql/mysql-bin.000002
//查看000002二进制日志文件的内容
---------------------------------------------------------------------------------------------------------
# at 203
#181214  0:43:07 server id 1  end_log_pos 337 CRC32 0x4209f33e Query thread_id=2 exec_time=0 error_code=0
use `client`/*!*/;
SET TIMESTAMP=1544719387/*!*/;
insert xinxi values ('000008','王五','女','018','23')
/*!*/;
# at 337
#181214  0:43:07 server id 1  end_log_pos 368 CRC32 0xf4cb4c7d Xid = 38
COMMIT/*!*/;
# at 368
#181214  0:43:15 server id 1  end_log_pos 451 CRC32 0xa428e268 Query thread_id=2 exec_time=0 error_code=0
SET TIMESTAMP=1544719395/*!*/;
BEGIN
/*!*/;
# at 451
#181214  0:43:15 server id 1  end_log_pos 585 CRC32 0xc3e48c8c Query thread_id=2 exec_time=0 error_code=0
SET TIMESTAMP=1544719395/*!*/;
insert xinxi values ('000009','赵六','男','019','37')
/*!*/;
# at 585
#181214  0:43:15 server id 1  end_log_pos 616 CRC32 0xf05f2902 Xid = 39
COMMIT/*!*/;
# at 616
#181214  0:45:59 server id 1  end_log_pos 663 CRC32 0xb3cc49ad Rotate to mysql-bin.000003  pos: 4
DELIMITER ;
# End of log file
ROLLBACK /* added by mysqlbinlog */;
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;

④通过查看二进制文件内容可以看到每个操作前都有一个id或者时间点,例如在时间点181214  0:43:15之前插入了王五的信息

例如执行下面操作可以只将数据恢复到181214  0:43:15,也就是说只恢复王五的信息,赵六的信息不恢复

[root@nnv5 mysql_bak]# mysqlbinlog --no-defaults --stop-datetime='2018-12-14  0:43:15' /usr/local/mysql/mysql-bin.000002 | mysql -uroot -p //恢复操作时间点之前的所有数据
mysql> mysql> select * from xinxi;  //查看xinxi表发现王五信息已经恢复了

如果执行下面操作是从181214  0:43:15这个时间点开始恢复以后的所有数据,因此只会恢复赵六的数据,王五的数据就跳过了

[root@nnv5 mysql_bak]# mysqlbinlog --no-defaults --start-datetime='2018-12-14  0:43:15' /usr/local/mysql/mysql-bin.000002 | mysql -uroot -p //恢复操作时间点之后的所有数据
mysql> mysql> select * from xinxi;  //查看xinxi表发现赵六信息已经恢复了

如果执行以下操作是指恢复时间点#181214  0:43:07#181214  0:45:59这个时间点之间的所有数据,如果前面或者时间点之后有数据则跳过不恢复 

[root@nnv5 mysql_bak]# mysqlbinlog --no-defaults --start-datetime='2018-12-14  0:43:07' --stop-datetime='2018-12-14 0:45:49'  /usr/local/mysql/mysql-bin.000002 | mysql -uroot -p
//恢复时间点0:43:07到 0:45:49之间的所有数据
mysql> mysql> select * from xinxi; //查看xinxi表发现王五和赵六信息已经恢复了