MySQL备份与恢复

一.备份的类型

1.热备

在数据库正常业务时,备份数据,并且能够一致性恢复(只能是innodb)
对业务影响非常小

2.温备

锁表备份,只能查询不能修改(myisam)
影响到写入操作

3.冷备

关闭数据库业务,数据库没有任何变更的情况下,进行备份数据.
业务停止

二.备份的方式

2.1逻辑备份

基于SQL语句的备份

1)binlog(备份SQL语句,DML,DCL,DDL,DTL)
2)into outfile(导出数据结果)

mysql> select * from world.city into outfile '/tmp/world_city.data';

3)mysqldump
4)replication(主从复制-延时从库)

5)mysqlblinlog

2.2物理备份

基于数据文件的备份

1)Xtrabackup(percona公司)

  1. cp $basedir/data

三.逻辑备份和物理备份的比较

3.1 mysqldump (MDP)

优点:
1.不需要下载安装
2.备份出来的是SQL,文本格式,可读性高,便于备份处理
3.压缩比较高,节省备份的磁盘空间

缺点:
依赖于数据库引擎,需要从磁盘把数据读出,然后转换成SQL进行转储,比较耗费资源,数据量大的话效率较低
建议:
100G以内的数据量级,可以使用mysqldump
超过TB以上,我们也可能选择的是mysqldump,配合分布式的系统
1EB  =1024 PB =1000000 TB

3.2 xtrabackup(XBK)

优点:
1.类似于直接cp数据文件,不需要管逻辑结构,相对来说性能较高
缺点:
1.可读性差
2.压缩比低,需要更多磁盘空间
建议:
>100G

四.备份策略

备份方式:
全备:全库备份,备份所有数据
增量:备份变化的数据
逻辑备份=mysqldump+mysqlbinlog
物理备份=xtrabackup_full+xtrabackup_incr+binlog或者xtrabackup_full+binlog
备份周期:
根据数据量设计备份周期
比如:周日全备,周1-周6增量

五.MySQL逻辑备份-mysqldump

客户端常用参数

mysqldump 
-u:指定用户
-p:指定密码
-h:指定主机域
-S:指定socket文件
-P:指定端口

1.全备参数:-A

[root@db02 ~]# mysqldump -A > /tmp/full.sql

2.指定库备份:-B(指定多个库)

[root@db02 ~]# mysqldump -B zls1 > /tmp/zls1.sql
#多了一条建库语句,use语句
mysql < /tmp/zls1.sql

3.什么都不加:备份库中的表

[root@db02 ~]# mysqldump zls1 > /tmp/zls1_1.sql

mysql> create database zls1;
mysql> use zls1; source /tmp/zls1_1.sql

mysql zls1 < /tmp/zls1_1.sql

4.备份时,刷新binlog:-F

[root@db01 ~]# mysqldump -A -F > /tmp/full_F.sql

[root@db01 ~]# mysqldump -B mysql zls  -F > /tmp/full_F.sql

5.打点备份:--master-data=2 以注释的形式,保存备份开始时间点的状态信息

#=2是注释
[root@db02 ~]# mysqldump -A --master-data=2 > /tmp/full1.sql

#=1 不注释
[root@db02 ~]# mysqldump -A --master-data=1 > /tmp/full1.sql

#=0 关闭
[root@db02 ~]# mysqldump -A --master-data=0 > /tmp/full1.sql
功能:
1)在备份时,会自动记录二进制日志文件名和位置号
0 默认值
1 以change master to 命令形式,可以用作主从复制
2 以注释的形式记录,备份时刻的文件名+position号
2)自动锁表
3)如果配合--single-transaction,支队非innoDB表进行锁表备份,innodb表进行热备,实际上是实现快照备份。

6.热备参数:--single-transaction(快照备份)

innodb 存储引擎开启热备(快照备份)功能
--master-data 可以自动加锁
1)在不加--single-transaction,启动所有的表的温备份,所有表都锁定。
2)加上--single-trabsaction,对innodb进行快照备份,对非innodb表可以实现自动锁表功能
[root@db02 ~]# mysqldump -A --master-data=2 --single-transaction > /tmp/full2.sql

7.-R(备份函数,存储过程),--triggers(备份触发器)

[root@db02 ~]# mysqldump -A -R --triggers --master-data=2 --single-transaction > /tmp/full2.sql

8.压缩备份:gzip

[root@db02 ~]# mysqldump -A -R --triggers --master-data=2 --single-transaction > /tmp/full2.sql

#恢复数据到数据库
[root@db02 ~]# zcat /tmp/full_2019-12-10.sql.gz | mysql -uroot -p123
#查找start-position 点
[root@db02 ~]# zcat /tmp/full_2019-12-10.sql.gz |head -22

9.-t:仅备份表结构

-d:仅备份数据

#只备份数据,不备份表结构
[root@db02 ~]# mysqldump -uroot -p12345 -t db1 >db_data.sql
#只备份表结构,不备份数据
[root@db02 ~]# mysqldump -uroot -p12345 -d db1 >db_t.sql

企业故障恢复案例

背景:
正在运行的网站系统,MySQL数据库,数据量25G,日业务增量10-15M。

备份策略:
每天23:00,计划任务调用mysqldump执行全备脚本

[root@db02 data]# mysqldump -A -R --triggers --master-data=2 --single-transaction|gzip > /backup/full_$(date +%F).sql.gz

故障时间点:
周三上午10点开发人员误删除一个核心业务表,如何恢复?

思路:

1.停库(避免二次伤害数据)

# 先停tomcat,php-fpm,nginx
[root@db02 ~]# /etc/init.d/mysqld stop

2.准备一个新环境

[root@db01 scripts]# ./mysql_install_db --user=mysql --basedir=/application/mysql --datadir=/application/mysql/data

[root@db01 scripts]# /etc/init.d/mysqld start

3.将昨天的全备,发送给新环境

[root@db02 ~]# scp /tmp/full_2019-12-11.sql.gz 172.16.1.51:/tmp

4.将全备导入新环境

[root@db01 scripts]# zcat /tmp/full_2019-12-11.sql.gz |mysql -uroot -p

5.截取昨天23点到今天10点之间的数据

[root@db02 data]# zcat /backup/full_2019-12-11.sql.gz |head -22

-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000003', MASTER_LOG_POS=809492;
#截取drop之前的binlog
[root@db02 data]# mysqlbinlog --base64-output=decode-rows -vvv mysql-bin.000003|less
818556

[root@db02 data]# mysqlbinlog --start-position=809492 --stop-position=818556 mysql-bin.000003 > /backup/inc.sql
#截取drop之后的binlog
818679
863424

[root@db02 data]# mysqlbinlog --start-position=818679 --stop-position=863424 mysql-bin.000003 > /backup/inc2.sql

[root@db02 data]# scp /backup/inc* 172.16.1.51:/root

6.恢复业务

  • a.直接使用临时库顶替原生产库,前端应用割接到新库
  • b.将误删除的表单独导出,然后导入到原生产环境

六.MySQL物理备份

1.MySQL物理备份工具-xtrabackup(XBK、Xbackup) 安装依赖包:

wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
yum -y install perl perl-devel libaio libaio-devel perl-Time-HiRes perl-DBD-MySQL libev

2.下载并安装xtrabackup

wget https://www.percona.com/downloads/XtraBackup/Percona-XtraBackup-2.4.12/binary/redhat/7/x86_64/percona-xtrabackup-24-2.4.12-1.el7.x86_64.rpm

https://www.percona.com/downloads/XtraBackup/Percona-XtraBackup-2.4.4/binary/redhat/6/x86_64/percona-xtrabackup-24-2.4.4-1.el6.x86_64.rpm

yum -y install percona-xtrabackup-24-2.4.4-1.el7.x86_64.rpm

3.备份策略

1.全量备份

2.增量备份

3.差异备份

4.备份方式

1.cp data

2.Xtrabackup(不支持事务)

3.innobackupex

1)对于非innodb表(比如myisam)是直接锁表cp数据文件,属于一种温备。
2)对于innodb的表(支持事务),不锁表,cp数据页最终以数据文件方式保存下来,并且把redo和undo一并备走,属于热备方式。
3)备份时读取配置文件/etc/my.cnf

5.自主定制备份路径名

[root@db01 ~]# mkdir /backup/full -p
#1.全量备份
[root@db01 ~]# innobackupex --user=root --password=123456 /backup/
[root@db01 /backup]# ls
2019-12-11_18-49-41  #默认的是生成带时间戳的文件件
[root@db01 ~]# innobackupex --user=root --password=123456 --no-timestamp /backup/full
#--no-timestamp 取消时间戳

6.备份集中多出来的文件:

-rw-r----- 1 root root       430 Dec 11 18:51 backup-my.cnf
-rw-r----- 1 root root        21 Dec 11 18:51 xtrabackup_binlog_info
-rw-r----- 1 root root       119 Dec 11 18:51 xtrabackup_checkpoints
-rw-r----- 1 root root       486 Dec 11 18:51 xtrabackup_info
-rw-r----- 1 root root      2560 Dec 11 18:51 xtrabackup_logfile
backup-my.cnf:数据库的配置文件
xtrabackup_binlog_info :(备份时刻的binlog位置)
[root@db01 /backup/full]# cat xtrabackup_binlog_info 
mysql-bin.000002    308
记录的是备份时刻,binlog的文件名字和当时的结束的position,可以用来作为截取binlog时的起点。
xtrabackup_info:备份的详细信息
xtrabackup_checkpoints :
backup_type = full-backuped 备份的类型
from_lsn = 0            上次所到达的LSN号(对于全备就是从0开始,对于增量有别的显示方法)
to_lsn = 160683027      备份开始时间(ckpt)点数据页的LSN    
last_lsn = 160683036    备份结束后,redo日志最终的LSN
compact = 0
recover_binlog_info = 0
(1)备份时刻,立即将已经commit过的,内存中的数据页刷新到磁盘(CKPT).开始备份数据,数据文件的LSN会停留在to_lsn位置。
(2)备份时刻有可能会有其他的数据写入,已备走的数据文件就不会再发生变化了。
(3)在备份过程中,备份软件会一直监控着redo的undo,如果一旦有变化会将日志也一并备走,并记录LSN到last_lsn。
从to_lsn  ----》last_lsn 就是,备份过程中产生的数据变化.

7.xbk 在innodb表备份恢复的流程

  0、xbk备份执行的瞬间,立即触发ckpt,已提交的数据脏页,从内存刷写到磁盘,并记录此时的LSN号
  1、备份时,拷贝磁盘数据页,并且记录备份过程中产生的redo和undo一起拷贝走,也就是checkpoint LSN之后的日志
  2、在恢复之前,模拟Innodb“自动故障恢复”的过程,将redo(前滚)与undo(回滚)进行应用
  3、恢复过程是cp 备份到原来数据目录下

8.恢复全备

#前提1:被恢复的目录是空的
#前提2:被恢复的数据库的实例是关闭的

#1.停库
[root@db01 ~]# systemctl stop mysqld
也可以使用/etc/init.d/mysqld stop 停库
#2.模拟CSR,做一遍redo,再做一遍undo
[root@db01 ~]# innobackupex --user=root --password=123456 --apply-log /backup/full

#3.保证data目录是空的
注意:如果是生产场景不建议删除,可以移除该目录到其它的目录下保存
[root@db01 ~]# mv /application/mysql/data/ /opt/

#4.恢复数据
[root@db01 ~]# innobackupex --user=root --password=123456 --copy-back /backup/full/
#5.授权
[root@db01 ~]# chown -R mysql.mysql /application/mysql/data
#6.启动数据库
[root@db01 ~]# systemctl start mysqld

9.innobackupex 增量备份(incremental)

备份恢复
(1)增量备份的方式,是基于上一次备份进行增量。
(2)增量备份无法单独恢复。必须基于全备进行恢复。
(3)所有增量必须要按顺序合并到全备中。
模拟备份数据
#1.先做全备
[root@db01 ~]# innobackupex --user=root --password=123456 --no-timestamp /backup/full_$(date +%F)
[root@db01 /backup/full_2019-12-11]# cat xtrabackup_checkpoints 
backup_type = full-backuped
from_lsn = 0
to_lsn = 1764255045
last_lsn = 1764263312
compact = 0
recover_binlog_info = 0

#2.第一次,增量备份(基于全备)
[root@db01 ~]# innobackupex --user=root --password=123456 --no-timestamp --incremental --incremental-basedir=/backup/full_$(date +%F) /backup/inc_$(date +%F-%H)
[root@db01 /backup/inc_2019-12-11-20]# cat xtrabackup_checkpoints 
backup_type = incremental
from_lsn = 1764255045
to_lsn = 1764255045
last_lsn = 1764322385
compact = 0
recover_binlog_info = 0

#3.第二次,增量备份(基于第一次增备)
注意:这里模拟的是每小时进行备份,注意修改时间
[root@db01 backup]# innobackupex --user=root --password=123456 --no-timestamp --incremental --incremental-basedir=/backup/inc_$(date +%F-%H -d "-1 hour") /backup/inc_$(date +%F-%H)

[root@db01 /backup/inc_2019-12-11-21]# cat xtrabackup_checkpoints 
backup_type = incremental
from_lsn = 1764255045
to_lsn = 1764452751
last_lsn = 1764471229
compact = 0
recover_binlog_info = 0

#4.第三次,增量备份(基于第二次增备)
注意:这里模拟的是每小时进行备份,注意修改时间
[root@db01 backup]# innobackupex --user=root --password=123456 --no-timestamp --incremental --incremental-basedir=/backup/inc_$(date +%F-%H -d "-1 hour") /backup/inc_$(date +%F-%H)
[root@db01 /backup/inc_2019-12-11-22]# cat xtrabackup_checkpoints 
backup_type = incremental
from_lsn = 1764452751
to_lsn = 1764538493
last_lsn = 1764551157
compact = 0
recover_binlog_info = 0

模拟恢复

1)full+inc1+inc2
2)需要将inc1和inc2按顺序合并到full中
3)分步骤进行--apply-log

第一步:停库

[root@db01 /backup]# systemctl stop mysqld

第二步:在全备中apply-log时,只应用redo,不应用undo

[root@db01 /backup]# innobackupex --user=root --password=123456 --apply-log --redo-only full_2019-12-11/

第三步:合并inc__2019-12-11-20合并到full中,并且apply-log,只应用redo,不应用undo

[root@db01 /backup]# innobackupex --user=root --password=123456 --apply-log --redo-only --incremental-dir=/backup/inc_2019-12-11-20 /backup/full_2019-12-11

第四步:合并inc_2019-12-11-21合并到full中,只做redo不做undo

[root@db01 /backup]#innobackupex --user=root --password=123456 --apply-log --redo-only --incremental-dir=/backup/inc_2019-12-11-21 /backup/full_2019-12-11

第五步:将合并inc_2019-12-11-22到full中,redo undo都做

[root@db01 /backup]# innobackupex --user=root --password=123456 --apply-log --incremental-dir=/backup/inc_2019-12-11-22 /backup/full_2019-12-11/

第六步:整体full执行apply-log,redo和undo都应用

[root@db01 /backup]# innobackupex --user=root --password=123456 --apply-log /backup/full_2019-12-11/

第七步:恢复数据

[root@db01 /backup]# mv /application/mysql/data /opt

[root@db01 /backup]# innobackupex --user=root --password=123456 --copy-back /backup/full_2019-12-11/

[root@db01 /backup]# chown -R mysql.mysql /application/mysql/data

第八步:截取binlog日志

第九步:启动数据库

[root@db01 /backup]# systemctl restart mysqld

第十步:导入截取的binlog日志

企业案例

思考:

企业级增量恢复实战

背景:
某大型网站,mysql数据库,数据量500G,每日更新量100M-200M

备份策略:
xtrabackup,每周六0:00进行全备,周一到周五及周日00:00进行增量备份。

故障场景:
周三下午2点出现数据库意外删除表操作。

全备:1次

增备:4次

00:00~14:00增量数据

模拟数据

#全备:周五的 24点(周六00点)
innobackupex --user=root --password=123 --no-timestamp /backup/full_$(date +%F)
[root@db01 backup]# cat full_2019-12-14/xtrabackup_checkpoints 
backup_type = full-backuped
from_lsn = 0
to_lsn = 23174130
last_lsn = 23174130
compact = 0
recover_binlog_info = 0


#第一次增备:周六的24点(周日的00点)
innobackupex --user=root --password=123 --no-timestamp --incremental --incremental-basedir=/backup/full_$(date +%F -d "-1 day") /backup/inc_$(date +%F)
[root@db01 backup]# cat inc_2019-12-15/xtrabackup_checkpoints 
backup_type = incremental
from_lsn = 23174130
to_lsn = 23199586
last_lsn = 23219800
compact = 0
recover_binlog_info = 0

#第二次增备:周日的24点(周一的00点)
innobackupex --user=root --password=123 --no-timestamp --incremental --incremental-basedir=/backup/inc_$(date +%F -d "-1 day") /backup/inc_$(date +%F)
[root@db01 backup]# cat inc_2019-12-16/xtrabackup_checkpoints 
backup_type = incremental
from_lsn = 23199586
to_lsn = 23250777
last_lsn = 23250777
compact = 0
recover_binlog_info = 0

#第三次增备:周一的24点(周二的00点)
innobackupex --user=root --password=123 --no-timestamp --incremental --incremental-basedir=/backup/inc_$(date +%F -d "-1 day") /backup/inc_$(date +%F)
[root@db01 backup]# cat inc_2019-12-17/xtrabackup_checkpoints 
backup_type = incremental
from_lsn = 23250777
to_lsn = 23250777
last_lsn = 23268489
compact = 0
recover_binlog_info = 0

#第四次增备:周二的24点(周三的00点)
innobackupex --user=root --password=123 --no-timestamp --incremental --incremental-basedir=/backup/inc_$(date +%F -d "-1 day") /backup/inc_$(date +%F)
[root@db01 backup]# cat inc_2019-12-18/xtrabackup_checkpoints 
backup_type = incremental
from_lsn = 23250777
to_lsn = 23299475
last_lsn = 23299475
compact = 0
recover_binlog_info = 0

思路:

1.先停库

/etc/init.d/mysqld stop

2.准备新环境

./mysql_install_db --user=mysql --basedir=/application/mysql --datadir=/application/mysql/data

3.清空新环境的data目录

rm -fr /application/mysql/data

4.数据合并

  • 将周六的全备,只做redo不做undo
[root@db01 backup]# innobackupex --apply-log --redo-only /backup/full_2019-12-14/
  • 将周日的增备合并到全备中,只做redo不做undo
[root@db01 backup]# innobackupex --apply-log --redo-only --incremental-dir=/backup/inc_2019-12-15 /backup/full_2019-12-14/
  • 将周一的增备合并到全备中,只做redo不做undo
[root@db01 backup]# innobackupex --apply-log --redo-only --incremental-dir=/backup/inc_2019-12-16 /backup/full_2019-12-14/
  • 将周二的增备合并到全备中,只做redo不做undo
[root@db01 backup]# innobackupex --apply-log --redo-only --incremental-dir=/backup/inc_2019-12-17 /backup/full_2019-12-14/
  • 将周三的增备合并到全备中,redo和undo都做
[root@db01 backup]# innobackupex --apply-log --incremental-dir=/backup/inc_2019-12-18 /backup/full_2019-12-14/
  • 将合并后的full目录整体做一次redo和undo

    [root@db01 backup]# innobackupex --apply-log /backup/full_2019-12-14/
    

恢复数据

  [root@db01 mysql]# innobackupex --copy-back /backup/full_2019-12-14/
  
  [root@db01 mysql]# chown -R mysql.mysql data

找数据位置点

#1.起始位置点
[root@db01 full_2019-12-14]# cat xtrabackup_binlog_info
mysql-bin.000001    13620168

#2.结束位置点
[root@db01 full_2019-12-14]# mysqlbinlog --base64-output=decode-rows -vvv /application/mysql/data_bak/mysql-bin.000001 |less
13638936

截取数据

[root@db01 full_2019-12-14]# mysqlbinlog --start-position=13620168 --stop-position=13638936 /application/mysql/data_bak/mysql-bin.000001 > /backup/inc_00_14.sql

13639060
13691523

[root@db01 full_2019-12-14]# mysqlbinlog --start-position=13639060 --stop-position=13691523 /application/mysql/data_bak/mysql-bin.000001 > /backup/inc_14.sql

恢复业务

  • 应用割接(修改代码,连接数据库的IP)
  • 备份表,导入旧库
[root@db01 mysql]# mysqldump zls1 student2 > /backup/student2.sql

[root@db01 mysql]# mysql zls1 < /backup/student2.sql 

10.差异备份恢复

模拟备份数据

第一步:全备

[root@db01 ~]# innobackupex --user=root --password=123456 --no-timestamp /backup/full

[root@db01 /backup/full]# cat xtrabackup_checkpoints 
backup_type = full-backuped
from_lsn = 0
to_lsn = 1764788859
last_lsn = 1764798807
compact = 0
recover_binlog_info = 0

*第二步:第一次差异备份

[root@db01 ~]# innobackupex --user=root --password=123456 --no-timestamp --incremental --incremental-basedir=/backup/full /backup/chayi1

[root@db01 /backup/chayi1]# cat xtrabackup_checkpoints 
backup_type = incremental
from_lsn = 1764788859
to_lsn = 1764804721
last_lsn = 1764809637
compact = 0
recover_binlog_info = 0

第三步:第二次差异备份

[root@db01 ~]# innobackupex --user=root --password=123456 --no-timestamp --incremental --incremental-basedir=/backup/full /backup/chayi2

[root@db01 /backup/chayi2]# cat xtrabackup_checkpoints 
backup_type = incremental
from_lsn = 1764788859
to_lsn = 1764848226
last_lsn = 1764863950
compact = 0
recover_binlog_info = 0

差异恢复数据

第一步:停库

[root@db01 ~]# systemctl stop mysqld

第二步:在全备中apply-log时,只应用redo,不应用undo

[root@db01 ~]# innobackupex --apply-log --redo-only /backup/full

第三步:合并最后一次差异备份,rebo,undo都做

[root@db01 ~]# innobackupex --apply-log --incremental-dir=/backup/chayi2 /backup/full

第四步:全备做redo,undo模拟CRS

[root@db01 ~]# innobackupex --apply-log /backup/full

第五步:执行copy-back恢复数据

[root@db01 ~]# mv /application/mysql/data/ /opt
[root@db01 ~]# innobackupex --copy-back /backup/full
[root@db01 ~]# chown -R mysql.mysql /application/mysql/data

第六步:截取binlog日志

第七步:启动数据库

[root@db01 ~]# systemctl start mysqld

第八步:导入截取的binlog日志

你可能感兴趣的:(MySQL备份与恢复)