MySQL备份与恢复 — 多种示例步骤

目录

备份的概念

重要性

备份分类

常见的备份方法

示例

冷备份

打包备份

模拟故障

恢复备份

热备份

导出

导出表

导出库

导出所有数据库

导入

导入表

导入库

导入所有数据库

增量备份与恢复

二进制日志

开启功能

生成日志

查看日志

查看加密内容

测试

恢复数据

模拟故障

恢复步骤

基于位置恢复

模拟故障

通过位置id来精确恢复数据

只指定开始id

只指定结束id

基于时间恢复

通过时间恢复数据

只指定开始时间

只指定结束时间


备份的概念

重要性

  • 在生产环境中,数据的安全性至关重要
  • 任何数据的丢失都可能产生严重的后果
  • 造成数据丢失的原因
    • 程序错误
    • 人为操作错误
    • 运算错误
    • 磁盘故障
    • 灾难(火灾、地震)和盗窃

备份分类

从物理与逻辑的角度,备份可分为:

  • 物理备份:对数据库操作系统中物理文件的备份
    • 方法
      • 冷备份(脱机备份):是在关闭数据库的时候进行的备份
      • 热备份(联机备份):数据库处于运行状态,依赖于数据库的二进制日志文件
      • 温备份:数据库锁定表格(不可写入但可读)的状态下进行备份操作
  • 逻辑备份:对数据库逻辑组件的备份(比如:表;等数据库对象)

从数据库的备份策略的角度,备份可分为:

  • 完全备份:每次对数据库进行完整的备份
  • 差异备份:只备份自从上次完全备份之后被修改过的文件
    • 如果要恢复数据,先恢复最近一次的完全备份,再恢复最近一次的差异备份
    • 如果做了多次差异备份,磁盘空间消耗大
  • 增量备份:只备份自从上次完全备份或增量备份后被修改的文件
    • 如果要恢复数据,先恢复最近一次的完全备份,再逐个恢复这个完全备份下一次的增量备份,直到最近一次的增量备份
    • 如果做了多次增量备份,磁盘空间消耗小

常见的备份方法

  • 物理冷备
    • 备份时数据库处于关闭状态,直接打包数据库文件
    • 备份速度快,恢复时也是最简单的
  • 专用备份工具mydump或mysqlhotcopy
    • mysqldump常用的逻辑备份工具
    • mysqlhotcopy仅拥有备份MyISAM和ARCHIVE表
  • 启用二进制日志进行增量备份
    • 进行增量备份,需要刷新二进制日志
  • 第三方工具备份
    • 免费的MySQL热备份软件Percona XtraBackup

示例

本博客的实验示例,因为要模拟故障,需要多次恢复快照,所以在安装完MySQL后,创建一个快照以便恢复

冷备份

登入MySQL后,创建一个名为auth的数据库,进入到该数据库后,创建一个用于测试的表

create database auth;
use auth;
create table users (user_name char(20) not null,user_passwd char(50) default '');

添加两行数据,实现以下效果,tom的密码被加密,jerry的密码明文显示

mysql> insert into users values ('tom', password('123'));
mysql> insert into users values ('jerry', '123');
mysql> select * from users;
+-----------+-------------------------------------------+
| user_name | user_passwd                               |
+-----------+-------------------------------------------+
| tom       | *23AE809DDACAF96AF0FD78ED04B6A265E05AA257 |
| jerry     | 123                                       |
+-----------+-------------------------------------------+

使用quit退出

mysql> quit

打包备份

实现冷备份需要mysql处于关闭状态,所以这里关闭mysqld服务

并且创建出存放备份文件的目录

[root@localhost ~]# systemctl stop mysqld
[root@localhost ~]# mkdir /bak

假如我们想要备份整个MySQL的程序和数据文件,那就备份MySQL的整个安装目录

使用tar命令将mysql整个安装目录打包成tar包,存放在/bak/ 目录下,命名为mysql_当天日期.tar.gz

+%F:表示以数字形式显示年月日

mysql/:表示需要打包的目录

[root@localhost ~]# cd /usr/local/
[root@localhost local]# ls
bin  etc  games  include  lib  lib64  libexec  mysql  sbin  share  src
[root@localhost local]# tar zcvf /bak/mysql_$(date +%F).tar.gz mysql/

然后cd到/bak/ 目录下就可以看到生成的tar包

[root@localhost local]# cd /bak/
[root@localhost bak]# ls
mysql_2024-07-26.tar.gz

模拟故障

这里模拟误操作

首先开启数据库服务

[root@localhost bak]# systemctl start mysqld

通过-e选项,将auth数据库删除,然后查询该库下的表,可以看到已经显示ERROR,查询不到了

到这里就完成模拟故障了

[root@localhost bak]# mysql -uroot -ppwd123 -e "drop database auth;"
mysql: [Warning] Using a password on the command line interface can be insecure.
[root@localhost bak]# mysql -uroot -ppwd123 -e "select * from auth.users;"
mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 1146 (42S02) at line 1: Table 'auth.users' doesn't exist

恢复备份

因为备份做的是冷备份,所以恢复备份的时候也需要MySQL是关闭状态

[root@localhost bak]# systemctl stop mysqld

解压备份的tar包,将旧的mysql安装目录重命名备份起来,以防其中的数据可能还会使用

再将解压后的备份目录移动到安装mysql的目录下,实现恢复

[root@localhost bak]# tar zxvf mysql_2024-07-26.tar.gz
[root@localhost bak]# cd /usr/local/
[root@localhost local]# ls
bin  etc  games  include  lib  lib64  libexec  mysql  sbin  share  src
[root@localhost local]# mv mysql/ mysql.bak
[root@localhost local]# mv /bak/mysql /usr/local/mysql

恢复完成后,启动mysqld服务,测试恢复的效果

[root@localhost local]# systemctl start mysqld

临时登录mysql的执行查询语句,可以看到,故障之前的数据被查询出来了,完成恢复

[root@localhost local]# mysql -uroot -ppwd123 -e "select * from auth.users;"
mysql: [Warning] Using a password on the command line interface can be insecure.
+-----------+-------------------------------------------+
| user_name | user_passwd                               |
+-----------+-------------------------------------------+
| tom       | *23AE809DDACAF96AF0FD78ED04B6A265E05AA257 |
| jerry     | 123                                       |
+-----------+-------------------------------------------+

热备份

在MySQL不停机的运行状态下进行备份操作

导出

mysqldump是mysql的一个导出工具,导出的文件实际上是一个脚本文件,运行这个脚本相当于在MySQL中输入了一系列的SQL语句,帮你把原本的对象创建出来

导出表

利用mysqldump来导出指定库中指定表的所有数据到指定的目录下

这里使用指定用户和密码,指定数据库和要在该库中导出的表 > 导出位置

[root@localhost ~]# mysqldump -uroot -ppwd123 auth users > /opt/auth-users.sql
导出库

这里直接去掉表名就是导出指定的数据库到指定位置

[root@localhost opt]# mysqldump -uroot -ppwd123 auth > /opt/auth.sql
导出所有数据库

如果要导出所有的数据库,不用再指定库或表,而是使用--all-databases选项,再指定导出位置就行了

  • --opt:优化执行速度
[root@localhost opt]# mysqldump -uroot --opt -ppwd123 --all-databases > /opt/all-data.sql

导入

导入表

导出的表可以导入到任何的数据库里,这里首先创建出一个名为"test"的数据库,用于导入的示例

直接使用mysql命令 指定要导入的数据库,然后使用重定向输入的符号,再指定要导入的文件绝对路径,就可以完成导入

[root@localhost opt]# mysql -uroot -ppwd123 -e "create database test;"
[root@localhost opt]# mysql -uroot -ppwd123 test < /opt/auth-users.sql
导入库

把指定的表换成库名就可以导入数据库了

  • 如果要导入的库已经存在,脚本文件会在该库内添加原有的表和其他各种信息
  • 如果要导入的库不存在,脚本文件会找不到该库,需要先创建出来该库,再执行
[root@localhost opt]# mysql -uroot -ppwd123 auth < /opt/auth.sql
导入所有数据库

使用mysql命令,不需要指定库或表,直接使用重定向输入,然后指定导入的sql文件即可

[root@localhost opt]# mysql -uroot -ppwd123 < /opt/all-data.sql

增量备份与恢复

增量备份(incremental backup)是备份的一个类型,是指在一次完全备份或上一次增量备份后,以后每次的备份只需备份与前一次相比增加或者被修改的文件。

二进制日志

开启功能

修改mysql配置文件,在[mysqld]模块中添加以下内容,然后重启mysql服务

[root@localhost ~]# vim /etc/my.cnf
[mysqld]
log-bin=mysql-bin
server-id=1
binlog_format=MIXED
[root@localhost ~]# systemctl restart mysqld
  • log-bin:日志生成的名称
  • server-id:指定服务器的标识,如果要构建一个主从架构的环境,两个设备的标识不能相同
  • binlog_format:指定复制方式
  • MIXED:混合复制方式
生成日志

此时我们cd进入mysql的data目录下

可以看到生成了两个文件:mysql-bin.000001mysql-bin.index

如果我们此时使用mysqladmin命令刷新日志文件

[root@localhost ~]# cd /usr/local/mysql/data/
[root@localhost data]# mysqladmin -u root -ppwd123 flush-logs

会发现在data目录下又生成了一个mysql-bin.000002文件

  • flush-logs:把当前缓冲区的SQL语句写入到现有的日志文件中(000001),然后生成一个新的日志文件(000002),准备接受新的日志信息
查看日志

使用mysqlbinlog命令查看二进制日志文件,但是此时我们并没有在mysql中执行SQL语句,所以日志文件中也没有记录相关的信息

[root@localhost data]# mysqlbinlog --no-defaults mysql-bin.000001
查看加密内容

在选项中使用base64来解码加密的行

[root@localhost data]# mysqlbinlog --no-defaults --base64-output=DECODE-ROWS mysql-bin.000001
测试

为了验证效果,逐个添加新的数据,并生成一个日志文件

先登录进mysql,然后添加一些数据,然后退出mysql,再刷新日志,此时日志信息就被记录到了000002的文件中

使用mysqlbinlog命令查看二进制日志文件(000002),就可以在日志文件中看到刚刚执行的SQL语句了

[root@localhost data]# mysql -uroot -ppwd123
mysql> use auth
mysql> insert into users values('aaa','123456');
mysql> insert into users values('bbb','123456');
mysql> insert into users values('ccc','123456');
mysql> insert into users values('ddd','123456');
mysql> insert into users values('eee','123456');
mysql> insert into users values('fff','123456');
mysql> quit
[root@localhost data]# mysqladmin -u root -ppwd123 flush-logs
[root@localhost data]# mysqlbinlog --no-defaults --base64-output=DECODE-ROWS mysql-bin.000002

恢复数据

恢复数据的前提是出现了故障,所以我们先模拟出现了故障

模拟故障

将测试恢复的表先删除掉

[root@localhost data]# mysql -u root -ppwd123 -e 'drop table auth.users;'
恢复步骤

先恢复完整备份,然后再通过二进制日志文件逐个恢复增量备份

[root@localhost data]# mysql -u root -ppwd123 auth < /opt/auth.sql

因为该类型日志文件是二进制的不能直接使用,所以先通过mysqlbinlog命令查询出来日志中的内容,通过管道符导入给mysql

然后可以使用select语句查询一下恢复的表,看看表中有没有被写入恢复的数据

[root@localhost data]# mysqlbinlog --no-defaults mysql-bin.000002 | mysql -u root -ppwd123
[root@localhost data]# mysql -u root -ppwd123 -e 'select * from auth.users;'

基于位置恢复

假如在操作数据库时,误删除了一行数据,不要直接insert去添加,而是通过二进制日志文件的位置id来实现精确恢复

模拟故障

再次删除users表,然后先恢复出上一次的完全备份

[root@localhost data]# mysql -u root -ppwd123 -e 'drop table auth.users;'
[root@localhost mysql]# mysql -u root -p auth < /opt/auth.sql

再查看日志内容,从日志中分析哪些数据还没有恢复,找出想要恢复到哪个数据的操作id

日志中带# at 数字 的行表示数据操作的位置id,可以根据开始id结束id恢来复单独的数据,但是结束id必须包含COMMIT的字段,代表数据存储到硬盘中,否则数据只是被存储在缓冲区内,并没有永久保存

在下方的内容中,开始id就是587,结束id就是732

[root@localhost mysql]# mysqlbinlog --no-defaults mysql-bin.000002
# at 587
#240726 22:44:45 server id 1  end_log_pos 701 CRC32 0xae04e527     Query    thread_id=3    exec_time=0    error_code=0
SET TIMESTAMP=1722005085/*!*/;
insert into users values('bbb','123456')
/*!*/;
# at 701
#240726 22:44:45 server id 1  end_log_pos 732 CRC32 0x5e9d9312     Xid = 11
COMMIT/*!*/;
# at 732

通过位置id来精确恢复数据

同时指定了开始id和结束id,mysqlbinlog会把两个id中间的操作全部执行一遍

[root@localhost mysql]# mysqlbinlog --no-defaults --start-position='587' --stop-position='732' mysql-bin.000002  | mysql -u root -p

只指定开始id

如果只指定了开始id,代表从开始id的位置,往后的指令全部执行一遍,直到文件末尾

[root@localhost mysql]# mysqlbinlog --no-defaults --start-position='587' mysql-bin.000002 | mysql -u root -p

只指定结束id

如果只指定了结束id,代表从日志开头到结束id的位置,中间的指令全部执行一遍

[root@localhost mysql]# mysqlbinlog --no-defaults --stop-position='521' mysql-bin.000002 | mysql -u root -p

基于时间恢复

在二进制日志文件中,还可以根据记录的时间来恢复数据

比如下方内容中的#240726 22:44:45#240726 22:45:20 是开始时间和结束时间

把两个时间点改为:2024-07-26 22:44:452024-07-26 22:45:20

利用这种格式,就可以使用mysqlbinlog命令进行基于时间的数据恢复

[root@localhost mysql]# mysqlbinlog --no-defaults mysql-bin.000002
# at 587
#240726 22:44:45 server id 1  end_log_pos 701 CRC32 0xae04e527     Query    thread_id=3    exec_time=0    error_code=0
SET TIMESTAMP=1722005085/*!*/;
insert into users values('bbb','123456')
/*!*/;
# at 701
#240726 22:44:45 server id 1  end_log_pos 732 CRC32 0x5e9d9312     Xid = 11
COMMIT/*!*/;
# at 732

通过时间恢复数据

同时指定了开始时间和结束时间,mysqlbinlog会把两个时间点中间的操作全部执行一遍

[root@localhost mysql]# mysqlbinlog --no-defaults --start-datetime='2024-07-26 22:44:45' --stop-datetime='2024-07-26 22:45:20' mysql-bin.000002 | mysql -u root -p

只指定开始时间

如果只指定了开始时间,代表从开始时间的位置,往后的指令全部执行一遍,直到文件末尾

[root@localhost mysql]# mysqlbinlog --no-defaults --start-datetime='2024-07-26 22:44:45' mysql-bin.000002 | mysql -u root -p

只指定结束时间

如果只指定了结束时间,代表从日志开头到结束时间的位置,中间的指令全部执行一遍

[root@localhost mysql]# mysqlbinlog --no-defaults --stop-datetime='2024-07-26 22:45:20' mysql-bin.000002 | mysql -u root -p

  • 38
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值