MySQL备份与恢复

数据库在信息系统中担任着很是重要的角色,尤为一些对数据可靠性要求很是高的行业,若是发生宕机或数据丢失,其损失是很是严重的。
在公司中备份的策略并非千篇一概的,而是根据每一个企业 的实际生产环境与业务需求制定合适的备份策略。不管是选择彻底备份仍是增量备份,都须要考虑它们的优缺点,是否适合当前的生产环境。同时为了保证恢复的完整性,建议开启二进制日志功能,二进制日志文件给恢复工做带来了很大的灵活性,能够基于时间点或位置进行恢复,考虑到数据库性能,能够将二进制日志文件保存在其余安全的硬盘中。mysql

在进行热备时,备份操做和应用服务在同时运行,这样十分消耗系统资源,致使数据库服务性能降低,这就要求咱们选择一个合适的时间(通常在应用负担很小的时候)再来进行备份操做。sql

须要注意的是,不是备份就万事大吉了,最好确认备份是否可用,因此备份以后的恢复测试是很是有必要的。同时备份时间也要灵活调整,如:数据库

数据更新频繁,则应该频繁地备份。
数据的重要性,在有适当更新时进行备份。
在数据库压力小的时间段进行备份,如一周一次彻底备份,天天进行增量备份。
中小公司,彻底备份通常一天一次便可。
大公司可每周进行一次彻底备份,天天进行一次增量备份。
尽可能为企业实现主从复制架构,以增长数据的可用性。
数据库备份类型能够从两个角度来看待:vim

一、从物理与逻辑的角度:安全

物理备份是对数据库操做系统的物理文件(如数据文件、日志文件等)的备份。这种类型的备份适用于在出现问题时须要快速恢复的大型重要数据库。架构

物理备份有能够分为如下几种类型:ide

①、冷备份:在数据库关闭状态下进行备份操做;性能

②、热备份:在数据库处于运行状态时进行备份操做,该备份方法依赖数据库的日志文件;测试

③、温备份:数据库锁定表格(不可写入,但可读取)的状态下进行备份;优化

逻辑备份是对数据库逻辑组件(如表等数据库对象)的备份,表示为逻辑数据库结构(create database、create table语句)和内容(insert语句或分隔文本文件)的信息。这种类型的备份使用于能够编辑数据值或表结构较小的数据量,或者在不一样的机器体系上从新建立数据。

二、从数据库的备份策略角度:

从数据库的备份策略角度,数据库的备份可分为彻底备份、差别备份和增量备份。其中呢,完整备份是实现差别、增量备份的基础。

完整备份:每次对数据进行完整的备份,即对整个数据库的备份。备份与恢复的操做很是简单,可是数据存在大量的重复,会占用大量的磁盘空间,备份的时间也很长。
差别备份:备份那些自从上次彻底备份以后被修改过的全部文件,备份的时间点是从上次完整备份起,备份数据会愈来愈大,恢复数据时,只需恢复上次的彻底备份和最近的一次差别备份。
增量备份:只有在那些在上次彻底备份或增量备份后被修改的文件才会被备份,以上次完整备份或上次增量备份的时间为时间点,仅仅备份这之间的数据变化,于是备份的数据量也小,占用空间小,备份速度快,但恢复时,须要从上一次的完整备份开始到最后一次增量备份之间的全部增量依次恢复,一旦中间的数据发生损坏,将致使数据的丢失。
备份实例:
一、物理冷备份与恢复:

[root@mysql /]# systemctl stop mysqld        #先停掉服务
[root@mysql /]# mkdir /backup            # 建立一个备份目录
[root@mysql /]# tar zcf /backup/mysql_all-$(date +%F).tar.gz /usr/local/mysql/data/         # 将整个数据库文件夹打包备份,(date +%F)当前日期
[root@mysql /]# ls -l /backup/      # 查看备份文件
total 732         # 总用量
-rw-r--r-- 1 root root 746839 Aug  2 14:48 mysql_all-2019-08-02.tar.gz     # 备份文件

来模拟数据库文件丢失:

[root@mysql /]# mkdir /diushi
[root@mysql /]# mv /usr/local/mysql/data/ /diushi/         # 将数据库存放目录移动到另外一个目录

恢复数据库:

[root@mysql /]# mkdir /restore/
[root@mysql /]# tar zxf /backup/mysql_all-2019-08-02.tar.gz -C   /restore/     # 要先将备份文件释放到一个空目录中,而后将须要的恢复到原位置
[root@mysql /]# mv /restore/usr/local/mysql/data/   /usr/local/mysql/         # 将数据库目录恢复到原位置
[root@mysql /]# systemctl restart mysqld             # 重启服务验证

二、mysqldump 备份与恢复:
备份数据库
备份指定库中的表:

mysqldump    [选项]    库名   表名  表名2   ……  > /备份路径/备份文件名
[root@mysql /]# mysqldump -u root -p test user   >   /backup/user-table.sql          # 将test库中的user表备份到backup目录中
Enter password:                   # 输入密码

备份一个或多个完整的库:

mysqldump   [选项]   --databases      库名1   库名2   ……  >  /备份路径/备份文件名
[root@mysql /]# mysqldump -u root -p  --databases  test mysql    >   /backup/databases.sql            # 将 test 和 mysql 库备份到backup中
Enter password:                       # 输入密码

备份 MySQL 中的全部库:

mysqldump   [选项]     --all-databases   >    /备份路径/备份文件名
[root@mysql /]# mysqldump -u root -p   --opt   --all-databases   >   all-data.sql          # --opt:优化执行速度
Enter password:          # 输入密码
[root@mysql /]# ls backup/            # 查看备份文件
all-data.sql      databases.sql       user-table.sql

恢复数据库:
恢复库中的表

mysql     [选项]   库名   <   /备份路径/备份文件名
[root@mysql /]# mysql -u root -p  test   <   /backup/user-table.sql    
Enter password: 
[root@mysql /]# mysql -u root -p -e ' show  tables  from  test;'           // 验证导入结果
Enter password: 
+----------------+
| Tables_in_test |
+----------------+
| user           |
+----------------+

恢复单个或多个库:

[root@mysql /]# mysql -u root -p -e ' drop database test;'     // 删除 test 数据库,模拟故障
Enter password: 
[root@mysql /]# mysql -u root -p -e ' show databases;'        // 验证 test 数据库是否存在
Enter password: 
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
+--------------------+
[root@mysql /]# mysql -u root -p   <   /backup/databases.sql     // 执行导入恢复操做
Enter password: 
[root@mysql /]# mysql -u root -p -e ' show databases;'       // 确认恢复后结果
Enter password: 
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| test               |
+--------------------+

MySQL 增量备份与恢复:
与彻底备份不一样,增量备份没有重复数据,备分量不大,时间段,但其恢复比较麻烦,须要上次彻底备份及彻底备份以后的全部增量备份以后才能恢复,并且要对全部增量备份逐个反推恢复。MySQL没有提供直接的增量备份办法,因此通常是经过MySQL提供的二进制日志来间接实现增量备份。

要进行MySQL的增量备份,首先须要开启二进制日志功能:

[root@mysql /]# mkdir /usr/local/mysql/logs            # 建立一个存放二进制日志文件的目录
[root@mysql /]# cd /usr/local/mysql/                       
[root@mysql mysql]# chown mysql:mysql logs/       # 设置目录归属,使其可以写入
[root@mysql /]# vim /etc/my.cnf                # 编写配置文件
[mysqld]
log-bin=/usr/local/mysql/logs/mysql-bin
[root@mysql /]# systemctl restart mysqld          # 重启服务,使配置生效
[root@mysql /]# ll /usr/local/mysql/logs/mysql-bin.*         # 目录下自动生成日志文件
-rw-rw---- 1 mysql mysql 120 Aug  2 17:04 /usr/local/mysql/logs/mysql-bin.000001
-rw-rw---- 1 mysql mysql  39 Aug  2 17:04 /usr/local/mysql/logs/mysql-bin.index

如今全部对数据库的修改,都将记录mysql-bin.000001文件中,当执行“mysqladmin -u root -p flush-logs”刷新二进制日志后,将会继续生成一个名为mysql-bin.000002的文件,以后全部的更改又将存在mysql-bin.000002文件中,以此类推,每刷新一次,就会生成一个新文件!
首先咱们在表中先录入一些信息,而后进行一次完整备份:

mysql> select * from user_info;
+------+----------+----------+
| id   | xingming | nianling |
+------+----------+----------+
| 001  | zhangsan |       20 |
| 002  | lisi     |       25 |
| 003  | wangwu   |       20 |
+------+----------+----------+
[root@mysql /]# mkdir /mysql_bak                # 建立一个备份存放位置
[root@mysql /]# mysqldump -u root -p   test user_info   > /mysql_bak/test_userinfo$(date +%F).sql           # 进行完整备份
Enter password: 
[root@mysql /]# ls /mysql_bak/               # 验证备份结果
test_userinfo2019-08-02.sql
[root@mysql /]# mysqladmin -u root -p flush-logs            # 刷新日志文件
Enter password: 
[root@mysql /]# ll /usr/local/mysql/logs/mysql-bin.*         # 生成新的日志文件000002
-rw-rw---- 1 mysql mysql 1192 Aug  2 17:18 /usr/local/mysql/logs/mysql-bin.000001
-rw-rw---- 1 mysql mysql  120 Aug  2 17:18 /usr/local/mysql/logs/mysql-bin.000002
-rw-rw---- 1 mysql mysql   78 Aug  2 17:18 /usr/local/mysql/logs/mysql-bin.index

继续录入新的数据,并进行增量备份:

mysql> select * from user_info;
+------+----------+----------+
| id   | xingming | nianling |
+------+----------+----------+
| 001  | zhangsan |       20 |
| 002  | lisi     |       25 |
| 003  | wangwu   |       20 |
| 004  | zhaoliu  |       20 |
| 005  | sunqi    |       30 |
+------+----------+----------+
[root@mysql /]# mysqladmin -u root -p flush-logs            # 刷新日志文件,这样在000002中只有两条数据的操做
Enter password: 
[root@mysql /]# cp /usr/local/mysql/logs/mysql-bin.000002 /mysql_bak/       # 将日志文件复制到备份目录中

模拟user_info 这个表被误删除了,恢复:

[root@mysql /]# mysql -u root -p test   <   /mysql_bak/test_userinfo2019-08-02.sql    # 先恢复完整备份
Enter password: 
[root@mysql /]# mysql -u root -p -e ' select * from test.user_info;'      # 查看一下确认,恢复成功
Enter password: 
+------+----------+----------+
| id   | xingming | nianling |
+------+----------+----------+
| 001  | zhangsan |       20 |
| 002  | lisi     |       25 |
| 003  | wangwu   |       20 |
+------+----------+----------+
[root@mysql /]# mysqlbinlog --no-defaults /mysql_bak/mysql-bin.000002 | mysql -u root -p                              # 恢复增量备份,--no-defaults 选项必需要有
[root@mysql /]# mysql -u root -p -e ' select * from test.user_info;'       # 确认,增量备份恢复成功
Enter password: 
+------+----------+----------+
| id   | xingming | nianling |
+------+----------+----------+
| 001  | zhangsan |       20 |
| 002  | lisi     |       25 |
| 003  | wangwu   |       20 |
| 004  | zhaoliu  |       20 |
| 005  | sunqi    |       30 |
+------+----------+----------+

下来就是基于位置恢复和基于时间点恢复了,这两种恢复是有很大的相同之处的,想要实现,必需先查看二进制日志文件来确认恢复的位置或时间点。

[root@mysql /]# mysqlbinlog --no-defaults /mysql_bak/mysql-bin.000002 
……      // 省略部份内容
#at 199               # 这一行就是操做ID号了
#190802 17:21:40 server id 1  end_log_pos 346 CRC32 0xc61c38c9  Query   thread_id=4 exec_time=0 error_code=0
use `test`/*!*/;
SET TIMESTAMP=1564737700/*!*/;
insert into user_info (id,xingming,nianling) values('004','zhaoliu','20')
/*!*/;
#at 346
#190802 17:21:40 server id 1  end_log_pos 377 CRC32 0xea2c7707  Xid = 50
COMMIT/*!*/;                   # 操做确认标记  谨记一条操做在此才算结束
#at 377
#190802 17:22:09 server id 1  end_log_pos 456 CRC32 0x6265a2a6  Query   thread_id=4 exec_time=0 error_code=0
SET TIMESTAMP=1564737729/*!*/;
BEGIN
/*!*/;
#at 456
#190802 17:22:09 server id 1  end_log_pos 601 CRC32 0x3727aeb7  Query   thread_id=4 exec_time=0 error_code=0
SET TIMESTAMP=1564737729/*!*/;
insert into user_info (id,xingming,nianling) values('005','sunqi','30')
/*!*/;
#at 601
#190802 17:22:09 server id 1  end_log_pos 632 CRC32 0x17c4779a  Xid = 51
COMMIT/*!*/;
#at 632
#190802 17:24:05 server id 1  end_log_pos 679 CRC32 0x9c698f03  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*/;
[root@mysql /]# mysqlbinlog --no-defaults --stop-position='456' /mysql_bak/mysql-bin.000002 | mysql -u root -p               # 恢复操做ID‘456’ 以前的操做
Enter password:

--start-position='456':表示为从操做456开始恢复,该日志文件456以前的数据不会恢复;
以上选项可更改成下面类型:
--stop-position='456':表示恢复到操做456就中止,该日志文件456以后的数据不会恢复;
基于时间点的恢复:
--start-datetime='2019-08-2 17:22:09':表示恢复该时间以后的数据;
--stop-datetime='2019-08-2 17:22:09':表示仅恢复该时间以前的数据;
谨记,全部类型的增量恢复以前,都必须先执行最近一次的彻底恢复。
谨记,全部类型的增量恢复以前,都必须先执行最近一次的彻底恢复。
谨记,全部类型的增量恢复以前,都必须先执行最近一次的彻底恢复。

相关文章
相关标签/搜索