一.备份的类型
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公司)
- 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日志