听说Mysql你很豪横?-------------呕心沥血深入解析mysql备份与恢复!!!

时间:2022-07-24
本文章向大家介绍听说Mysql你很豪横?-------------呕心沥血深入解析mysql备份与恢复!!!,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

一、mysql数据库备份类型

1、各种类型备份原理

物理备份 : 文件备份,直接在linux系统上拷贝 逻辑备份 : 库备份,表备份–>>数据库sql脚本 (1) 完整性备份 所有的全部备份 生成所有的sql脚本 (2) 增量备份 完整性为前提 后面完整加上 增加的内容 与上一次进行比较 如果其中间的一个凉了 数据就会丢掉那一层的增量 数据就会丢失 (3) 差异备份 完整性为前提 相比较完整性备份 多出来的3 4

2、从物理与逻辑的角度,如何分类备份?

物理备份:对数据库操作系统的物理文件(如数据文件、日志文件等)的备份 数据库在物理层面分成了三类文件,每一个文件的名字以表的名字开始,扩展名指出文件类型

  • 表结构文件:.frm文件存储表定义
  • 表数据文件的扩展名为.MYD( MYData)
  • 表索引文件的扩展名是.MYI( MYIndex)

物理备份又可以分为脱机备份(冷备份)和联机备份(热备份)

  • 冷备份:是在关闭数据库的时候进行的 给数据库down掉
  • 热备份:数据库处于运行状态,这种备份方法依赖于数据库的日志文件
  • 温热备:数据库锁定表格(不可写入但可读)的状态下进行备份操作

逻辑备份:对数据库逻辑组件(如表等数据库对象)的备份 生成一条条sql语句

3、从数据库的备份策略角度分类

完全备份:每次对数据进行完整的备份 差异备份:备份那些自从上次完全备份之后被修改过的文件 增量备份:只有那些在上次完全备份或者增量备份后被修改的文件才会被备份

二:MySQL的完全备份

1、完全备份介绍

完全备份是对整个数据库的备份、数据库结构和文件结构的备份 完全备份保存的是备份完成时刻的数据库 完全备份是增量备份的基础

2、完全备份的优缺点

优点:

  • 安全性高
  • 备份与恢复操作简单方便 缺点:
  • 数据存在大量的重复
  • 占用大量的备份空间,空间利用率低
  • 备份与恢复时间长

现网中一般第一次使用完全备份 第二次以后直接用增量备份

3、备份方式

(1)直接在linux上打包备份文件

直接打包数据库文件夹,如/usr/local/mysql/data

如:tar jcvf /opt/mysql-$(date +%F).tar.gz /usr/local/mysql/data

(2)使用专用备份工具 mysqldump

mysqldump命令是MySQLI自带的备份工具,相当方便对MySQL进行备份 通过该命令工具可以将指定的库、表或全部的库导出为SQL脚本,在需要恢复时可进行数据恢复 .sql脚本 备份单个库 是备份所有表 还原的时候要先创建此数据库 语法:

mysqldump -u 用户名 -p [密码] [选项] [库名] > /备份路径/备份文件名
例如:
mysqldump -u root -p yiku > /backup/yiku.sql

4、mysqldump

(1)备份单个库

mysqldump -uroot -p -p shang > /opt/shang.sql   
vim /opt/shang.sql

DROP TABLE IF EXISTS `info`;       ' if判断  如果info这个表已经存在  就进行删除'
/*!40101 SET @saved_cs_client     = @@character_set_client */;       '   /*代表注释'
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `info` (                                   '    创建表结构'
  `id` int(11) NOT NULL,
  `name` char(4) NOT NULL,
  `score` decimal(5,2) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;

(2)备份多个库

[root@promote opt]# mysqldump -u root -pAbc123 --databases dog shang > /opt/shang_dog.sql

(3)备份所有库

[root@promote opt]# mysqldump -uroot -pAbc123 --opt --all-databases > /opt/all.sql

(4)单独备份表

[root@promote opt]# mysqldump -uroot -pAbc123 shang info > /opt/shang_info.sql
[root@promote opt]# mysqldump -uroot -pAbc123 -d shang info > /opt/shang_info.sql     '只备份表结构'

三、数据库还原

1、数据恢复的两种方法

使用 mysqldump命令导出的SQL备份脚本,在进行数据恢复时可使用以下方法导入 source命令 mysql命令

2、使用source命令恢复数据库

使用 source恢复数据库的步骤 登录到 MySQL数据库 执行 source备份sql脚本的路径(绝对路径)

mysql> show tables;   ' 看一下表结构'
+-----------------+
| Tables_in_shang |
+-----------------+
| info            |
+-----------------+
1 row in set (0.00 sec)

mysql> drop table info;     '删除表'
Query OK, 0 rows affected (0.01 sec)

mysql> source /opt/shang.sql    '还原刚刚备份的/opt/shang.sql '
Query OK, 0 rows affected (0.00 sec)

Query OK, 0 rows affected (0.00 sec)


mysql> show tables;         '再重新查看一下是否备份成功'
+-----------------+ 
| Tables_in_shang |
+-----------------+
| info            |
+-----------------+
1 row in set (0.00 sec)

mysql> select * from info;     '  查看一下表内容'
+----+------+-------+
| id | name | score |
+----+------+-------+
|  1 | zhen | 99.00 |
|  2 | qqqq | 88.00 |
|  3 | wwww | 77.00 |
+----+------+-------+
3 rows in set (0.01 sec)

3、如何使用mysql命令恢复数据库?

语法: mysql -u 用户名 -p [密码] < 库备份脚本的路径 ‘//此处用了导入<符号,而不是导出>符号’ 例如 mysql -u root -p < /backup/all-data.sql

mysql> drop table info;   '先将之前的表删除'
mysql> exit
[root@promote opt]# mysql -u root -pAbc123 < /opt/all.sql  '将之前备份的全部覆盖过来'
[root@promote opt]# mysql -u root -pAbc123              '再次登录'
mysql> use shang;       '进入到shang这个库中'
mysql> show tables;      '看一下info的表'
+-----------------+
| Tables_in_shang |
+-----------------+
| info            |
+-----------------+
1 row in set (0.00 sec)

四、增量备份

1、mysql增量备份的方法

MySQL没有提供直接的增量备份方法

可以通过 MySQL提供的二进制日志( binary logs)间接实现增量备份

MySQL的配置文件的[mysqld]项中加入log-bin=filepath项(filepath是二进制文件的路径),如log-bin=mysql-bin,然后重启mysqld服务。

二进制日志文件的默认路径为/usr/local/mysql/data

[root@localhost ~]# vim /etc/my.cnf
'//在[mysqld]项中加入配置 log-bin=mysql-bin'
...省略内容
[mysqld]
user = mysql
basedir = /usr/local/mysql
datadir=/usr/local/mysql/data
port = 3306
character_set_server=utf8
pid-file = /usr/local/mysql/mysqld.pid
socket = /usr/local/mysql/mysql.sock
server-id = 1
log-bin=mysql-bin	'//添加此句'
...省略内容
[root@localhost ~]# systemctl restart mysqld	'//重启服务'
[root@localhost ~]# ls /usr/local/mysql/data/
...省略内容
mysql-bin.000001	'//发现已经生成了二进制文件,设置成功'
...省略内容

只需定时执行 flush-logs方法重新创建新的日志,生成二进制文件序列,并及时把这些旧的日志保存到安全的地方就完成了一个时间段的增量备份

语法
mysqladmin -u 用户名 -p [密码] flush-logs

2、有什么方式进行增量恢复?

(1)查看增量备份信息—64位转码

mysqlbinlog --no-defaults --base64-output=decode-rows -v 日志文件名称 /opt/aaa.txt	'//使用64位解码器按行输出日志文件放到/opt/aaa.txt中'
cat /opt/aaa.txt  '//查看日志文件的详细信息'

(2)一般恢复

语法
mysqlbinlog [--no-defaults] 增量备份文件 | mysql -u 用户名 -p

(3)断点恢复

基于位置恢复

就是将某个起始时间的二进制日志导入数据库中,从而跳过某个发生错误的时间点实现数据的恢复

恢复数据到指定位置
mysqlbinlog --stop-position='操作id' 二进制日志 |mysql -u 用户名 -p 密码
从指定的位置开始恢复数据
mysqlbinlog --start-position='操作id' 二进制日志 |mysql -u 用户名 -p 密码

(4)基于时间点恢复

使用基于时间点的恢复,可能会出现在一个时间点里既同时存在正确的操作又存在错误的操作,所以我们需要一种更为精确的恢复方式

从日志开头截止到某个时间点的恢复
mysqlbinlog [--no-defaults] --stop-datetime='年-月-日 小时:分钟:秒' 二进制日志 |mysql -u 用户名 -p 密码

从某个时间点到日志结尾的恢复
mysqlbinlog [--no-defaults] --start-datetime='年-月-日 小时:分钟:秒' 二进制日志 |mysql -u 用户名 -p 密码

从某个时间点到某个时间点的恢复
mysqlbinlog [--no-defaults] --start-datetime='年-月-日 小时:分钟:秒' --stop-datetime='年-月-日 小时:分钟:秒

五、基于断点恢复、时间点恢复实验

1、实验思路:

  • 开启增量备份 ,在主配置文件内加入log-bin=mysql-bin
  • 进行一次完全备份
  • 模拟误操作实验 首先添加一个字段 然后模拟误删除一个字段 在进行正常操作加入一个字段,这样的话误操作被夹在中间 ,此时进行完整备份将不能达到需求,所以产生了基于时间点恢复和操作号恢复两种方式

(1)第一步开启二进制日志文件

vim /etc/my.cof   将下列字段
[mysqld]
user = mysql
basedir = /usr/local/mysql
datadir=/usr/local/mysql/data
port = 3306
character_set_server=utf8
pid-file = /usr/local/mysql/mysqld.pid
socket = /usr/local/mysql/mysql.sock
log-bin=mysql-bin    '添加此段信息'
server-id = 1
#skip-grant-tables
[root@promote opt]# systemctl restart mysqld
[root@promote opt]# cd /usr/local/mysql/data/   '进入到mysql的主配置文件'
[root@promote data]# ls
aaa       ib_buffer_pool  ibtmp1            performance_schema
auto.cnf  ibdata1         mysql             school
dog       ib_logfile0     mysql-bin.000001    '发现已经产生二进制文件'
  shang
dogpeng   ib_logfile1     mysql-bin.index   sys

(2)第二步 进行一次完全备份

[root@promote data]# mysqldump -uroot -pAbc123 shang >/opt/shang.sql
[root@promote data]# cd /opt
[root@promote opt]# ls   '发现已经产生sql备份文件'
mysql  mysql-2020-08-23.tar.xz  rh  shang.sql
[root@promote opt]# 

之前的001存放的是之前的操作 ,新建一个002文件来存放接下来要存放的内容

[root@promote opt]# mysqladmin -uroot -pAbc123 flush-logs  '重新生成一个日志文件'
mysqladmin: [Warning] Using a password on the command line interface can be insecure.
[root@promote opt]# ls /usr/local/mysql/data/
aaa       ib_buffer_pool  ibtmp1            mysql-bin.index     sys
auto.cnf  ibdata1         mysql             performance_schema
dog       ib_logfile0     mysql-bin.000001  school
dogpeng   ib_logfile1     mysql-bin.000002  shang

(3)模拟误操作实验

模拟实验环境需求: 管理员误操作 将表中的的qqqq删除 又正常添加的rrrr ,误操作被夹在中间

mysql> use shang;    '进入到shang的库中'
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> select * from info;     '查看库中所有表的信息'
+----+------+-------+
| id | name | score |
+----+------+-------+
|  1 | zhen | 99.00 |
|  2 | qqqq | 88.00 |
|  3 | wwww | 77.00 |
+----+------+-------+
3 rows in set (0.00 sec)

mysql> insert into info values(4,'eeee',66);    '此时插入一条表信息'
Query OK, 1 row affected (0.00 sec)


mysql> delete from info where name='qqqq';    '模拟误删除  ,删除qqq'
Query OK, 1 row affected (0.00 sec)
mysql> insert into info values(5,'rrrr',55);   '此时又插入一条正常的操作'
Query OK, 1 row affected (0.01 sec)
mysql> select * from info;   '再次查看表信息   '
+----+------+-------+
| id | name | score |
+----+------+-------+
|  1 | zhen | 99.00 |
|  3 | wwww | 77.00 |
|  4 | eeee | 66.00 |
|  5 | rrrr | 55.00 |
+----+------+-------+
4 rows in set (0.00 sec)

mysql> 

[root@promote opt]# mysqladmin -uroot -pAbc123 flush-logs  '再次生成文件'
[root@promote opt]# ls /usr/local/mysql/data/  '此时生成003文件 ,刚才的误操作在002中 此时得003 是为了存放新的日志文件'
aaa       ib_buffer_pool  ibtmp1            mysql-bin.000003    shang
auto.cnf  ibdata1         mysql             mysql-bin.index     sys
dog       ib_logfile0     mysql-bin.000001  performance_schema
dogpeng   ib_logfile1     mysql-bin.000002  school

[root@promote data]# mysqlbinlog --no-defaults mysql-bin.000002  '查看002的日志文件 '
[root@promote data]# mysqlbinlog --no-defaults --base64-output=decode-rows -v mysql-bin.000002 >/opt/bak.txt   '转码到opt下'


[root@promote data]# vim /opt/bak.txt 
# at 834         '执行编号'
#200823 13:29:27 server id 1  end_log_pos 888 CRC32 0xa581c15e  Table_map:   '执行时间'`shang`.`info` mapped to number 127
# at 888
#200823 13:29:27 server id 1  end_log_pos 936 CRC32 0xc3d240d8  Write_rows: table id 127 flags: STMT_END_F
### INSERT INTO `shang`.`info`
### SET
###   @1=5
###   @2='rrrr'
###   @3=55.00
# at 936

2、基于时间进行数据恢复

找到误操作时间点 200823 13:29:04 —stop-datatime 意味着你在文件的最头部 一直执行到目前这个点

200823 13:29:27------ start-datetime 意味着从这个点在开始执行

-通过这样的 方式使得中间的误操作就越过去不执行了

[root@localhost opt]# vim bak.txt 
#200823 13:29:04 server id 1  end_log_pos 665 CRC32 0x9ca93efb  Delete_rows: table id 127 flags: STMT_END_F    
### DELETE FROM `shang`.`info`    进入到日志文件 ,找到误操作的行  
#200823 13:29:27 server id 1  end_log_pos 936 CRC32 0xc3d240d8  Write_rows: table id 127 flags: STMT_END_F
### INSERT INTO `shang`.`info`     误操作行的下一个正常执行的行

(1) 断点恢复之前先进行完全恢复

mysql> use shang;
Database changed
mysql> source /opt/shang.sql;

mysql> select * from info;
+----+------+-------+
| id | name | score |
+----+------+-------+
|  1 | zhen | 99.00 |
|  2 | qqqq | 88.00 |
|  3 | wwww | 77.00 |
+----+------+-------+

(2)–stop-datetime

这里的日期形式是 年-月-日 要改一下形式 不然会报错

[root@localhost opt]# mysqlbinlog --no-defaults --stop-datetime='2020-08-23 13:29:04' /usr/local/mysql/data/mysql-bin.000002 | mysql -uroot -pAbc123

mysql> select * from info;  '再次查看表  发现之后加入的eeee已经恢复上去了'
+----+------+-------+
| id | name | score |
+----+------+-------+
|  1 | zhen | 99.00 |
|  2 | qqqq | 88.00 |
|  3 | wwww | 77.00 |
|  4 | eeee | 66.00 |
+----+------+-------+
4 rows in set (0.00 sec)

(3) --start-datetime

[root@localhost opt]# mysqlbinlog --no-defaults --start-datetime='2020-08-23 13:29:27' /usr/local/mysql/data/mysql-bin.000002 | mysql -uroot -p
mysql> use shang;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> select * from info;
+----+------+-------+
| id | name | score |
+----+------+-------+
|  1 | zhen | 99.00 |
|  2 | qqqq | 88.00 |
|  3 | wwww | 77.00 |
|  4 | eeee | 66.00 |
|  5 | rrrr | 55.00 |
+----+------+-------+

3、基于时间点at进行恢复

at 563 --stop-position 误删除的开始节点 at 655 --start-position 误删除的结束节点

# at 563
#200823 13:29:04 server id 1  end_log_pos 617 CRC32 0xd664ad61  Table_map: `shang`.`info` mapped to number 127
# at 617
#200823 13:29:04 server id 1  end_log_pos 665 CRC32 0x9ca93efb  Delete_rows: table id 127 flags: STMT_END_F
### DELETE FROM `shang`.`info`
### WHERE
###   @1=2
###   @2='qqqq'
###   @3=88.00
# at 665

(1)对刚才恢复成功的进行删除

mysql> delete from info where id=4;
Query OK, 1 row affected (0.00 sec)

mysql> delete from info where id=5;
Query OK, 1 row affected (0.00 sec)

mysql> select * from info;
+----+------+-------+
| id | name | score |
+----+------+-------+
|  1 | zhen | 99.00 |
|  2 | qqqq | 88.00 |
|  3 | wwww | 77.00 |
+----+------+-------+
3 rows in set (0.00 sec)

(2) --stop-position

[root@localhost opt]# mysqlbinlog --no-defaults --stop-position='563' /usr/local/mysql/data/mysql-bin.000002 | mysql -uroot -p



mysql> select * from info;
+----+------+-------+
| id | name | score |
+----+------+-------+
|  1 | zhen | 99.00 |
|  2 | qqqq | 88.00 |
|  3 | wwww | 77.00 |
|  4 | eeee | 66.00 |
+----+------+-------+
4 rows in set (0.00 sec)

(3)–start-position

此时655节点一直报错 经查阅资料发现 --start-position=‘655’ 是个存储过程的中间位置,无法直接读取,所以会报错 就将start改成下一字段就好了

[root@localhost opt]# mysqlbinlog --no-defaults --start-position='655' /usr/local/mysql/data/mysql-bin.000002 | mysql -uroot -p
Enter password: ERROR: Error in Log_event::read_log_event(): 'read error', data_len: 1107206300, event_type: 88
ERROR: Could not read entry at offset 655: Error in log format or read error.
[root@localhost opt]# mysqlbinlog --no-defaults --start-position='696' /usr/local/mysql/data/mysql-bin.000002 | mysql -uroot -p

mysql> use shang;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> select * from info;
+----+------+-------+
| id | name | score |
+----+------+-------+
|  1 | zhen | 99.00 |
|  2 | qqqq | 88.00 |
|  3 | wwww | 77.00 |
|  4 | eeee | 66.00 |
|  5 | rrrr | 55.00 |
+----+------+-------+
5 rows in set (0.00 sec)