本章内容
备份和恢复简介
实验一:实现Mariadb的冷备份和恢复
实验二:实现基于LVM的备份还原,结合binlog恢复最新状态
mysqldump简介与用法
实验三:数据库数据文件损坏,如何还原最新状态?
实验四:误删除表,如何恢复最新状态?
xtrabackup简介与用法
实验五: Xtrabackup完全备份及还原
实验六: Xtrabackup完全,增量备份及还原
实验七: Xtrabackup单表导出和导入
备份和恢复
为什么要备份
灾难恢复:硬件故障、软件故障、自然灾害、黑|客攻|击、误操作测试等数据丢失场景
备份注意要点
能容忍最多丢失多少数据
恢复数据需要在多长时间内完成
需要恢复哪些数据
还原要点
做还原测试,用于测试备份的可用性
还原演练
备份类型:
完全备份,部分备份
完全备份:整个数据集
部分备份:只备份数据子集,如部分库或表
完全备份、增量备份、差异备份
增量备份:仅备份最近一次完全备份或增量备份(如果存在增量)以来变化的数据,备份较快,还原复杂
差异备份:仅备份最近一次完全备份以来变化的数据,备份较慢,还原简单
注意:二进制日志文件不应该与数据文件放在同一磁盘
冷、温、热备份
冷备:读写操作均不可进行
温备:读操作可执行;但写操作不可执行
热备:读写操作均可执行
MyISAM:温备,不支持热备
InnoDB: 都支持
物理和逻辑备份
物理备份:直接复制数据文件进行备份,与存储引擎有关,占用较多的空间,速度快
逻辑备份:从数据库中“导出”数据另存而进行的备份,与存储引擎无关,占用空间少,速度慢,可能丢失精度
备份时需要考虑的因素
温备的持锁多久
备份产生的负载
备份过程的时长
恢复过程的时长
备份什么
数据
二进制日志、InnoDB的事务日志
程序代码(存储过程、存储函数、触发器、事件调度器)
服务器的配置文件
备份工具
cp, tar等复制归档工具:物理备份工具,适用所有存储引擎;只支持冷备;完全和部分备份
LVM的快照:先加锁,做快照后解锁,几乎热备;借助文件系统工具进行备份
mysqldump:逻辑备份工具,适用所有存储引擎,温备;支持完全或部分备份;对InnoDB存储引擎支持热备,结合binlog的增量备份
xtrabackup:由Percona提供支持对InnoDB做热备(物理备份)的工具,支持完全备份、增量备份
MariaDB Backup: 从MariaDB 10.1.26开始集成,基于Percona XtraBackup 2.3.8实现
mysqlbackup:热备份, MySQL Enterprise Edition组件
mysqlhotcopy:几乎冷备;仅适用于MyISAM存储引擎
重点掌握mysqldump和xtrabackup
实验一:实现Mariadb的冷备份和恢复
需要停服务,不推荐
数据库初始状态
1、备份过程
systemctl stop mariadb #停止数据库服务 tar Jcvf /data/all.tar.xz /var/lib/mysql #打包整个数据库文件夹 (生产环境中应把备份文件拷到另一台服务器上)
2、模拟数据损坏
rm -rf /var/lib/mysql/*
3、恢复过程
tar xvf /data/all.tar.xz #解包备份文件 mv var/lib/mysql/* /var/lib/mysql/ #还原数据库文件 systemctl restart mariadb #启动服务
查看数据库,确认恢复成功
实验二:实现基于LVM的备份还原,结合binlog恢复最新状态
需要数据目录在逻辑卷中,二进制日志可以不在逻辑卷里
加读锁的时间很短,几乎是热备
一、备份过程
1、创建LVM
创建一个新分区/dev/sda6 pvcreate /dev/sda6 vgcreate vg0 /dev/sda6 vgcreate vg0 /dev/sda6 lvcreate -L 5G -n lv_mysql vg0 #创建数据卷 lvcreate -L 5G -n lv_binlog vg0 #创建二进制日志卷 mkfs.ext4 /dev/vg0/lv_mysql mkfs.ext4 /dev/vg0/lv_binlog mkdir /data/{mysql,binlog} mount /dev/vg0/lv_mysql /data/mysql mount /dev/vg0/lv_binlog /data/binlog
chown -R mysql.mysql /data/mysql #修改目录权限 chown -R mysql.mysql /data/binlog
2、配置数据库
vim /etc/my.cnf
datadir=/data/mysql #指定数据目录 log_bin=/data/binlog/mysql-bin #指定二进制日志目录 binlog_format=row #二进制日志记录的格式,改成row innodb_file_per_table #每个表单独存放一个文件 character_set_server=utf8 #字符集为UTF-8
systemctl restart mariadb mysql>create database hellodb; #创建一个测试数据库hellodb
3、开始备份
mysql > flush tables with read lock; #加读锁 mysql> flush logs; #切换二进制日志文件 mysql> show master logs; #记录文件名和position,如mysql-bin.000004,245
lvcreate -n lv_mysql_snap -L 1G -s -p r /dev/vg0/lv_mysql #创建快照 mysql> unlock tables; #解锁,加锁到解锁的过程速度要快 mount -o nouuid,norecovery /dev/vg0/lv_mysql_snap /mnt #挂载快照卷 (-o选项针对xfs文件系统)
cp -a /mnt/* /backup/ #备份快照里的内容 umount /mnt #取消挂载 lvremove /dev/vg0/lv_mysql_snap #删除快照卷,不然数据库的速度会变慢
二、还原过程
1、对数据库再进行一些修改
mysql> create database testdb; #再创建一个测试数据库testdb
2、模拟数据损坏
rm -rf /data/mysql/* systemctl stop mariadb
3、还原备份的数据文件
cp -av /backup/* /data/mysql
4、禁止用户连接
vim /etc/my.cnf skip-networking #添加此行
systemctl start mariadb
或
iptables禁止用户连接
5、恢复binlog中最新日志到数据库中
mysqlbinlog --start-position=245 mysql-bin.000004 > /backup/bin.sql mysqlbinlog mysql-bin.00005 >> /backup/bin.sql mysql6、确认数据库恢复
mysql>show databases; 能够看到最新的testdb数据库,确认已恢复至最新7、恢复用户访问
vim /etc/my.cnf skip_networking删除此行 systemctl restart mariadb或
iptables允许用户连接
逻辑备份工具
逻辑备份工具:mysqldump, mydumper, phpMyAdmin
Schema和数据存储在一起、巨大的SQL语句、单个巨大的备份文件
mysqldump工具:客户端命令,通过mysql协议连接至mysqld服务器进行备份
mysqldump [OPTIONS] database [tables] mysqldump [OPTIONS] -B DB1 [DB2 DB3...] mysqldump [OPTIONS] -A [OPTIONS]mysqldump参考: https://dev.mysql.com/doc/refman/5.7/en/mysqldump.html
mysqldump适用于相对不那么大的数据库,因为使用mysql协议,速度比较慢
mysqldump常见选项:
-A, --all-databases 备份所有数据库,含create database
-B , --databases db_name… 指定备份的数据库,包括create database语句
-E, --events:备份相关的所有event scheduler
-R, --routines:备份所有存储过程和存储函数
--triggers:备份表相关触发器,默认启用,用--skip-triggers,不备份触发器
--master-data[=#]: 此选项须启用二进制日志
1:所备份的数据之前加一条记录为CHANGE MASTER TO语句,非注释,不指定#,默认为1
2:记录为注释的CHANGE MASTER TO语句
此选项会自动关闭--lock-tables功能,自动打开--lock-all-tables功能(除非开启--single-transaction)
-F, --flush-logs :备份前滚动日志,锁定表完成后,执行flush logs命令,生成新的二进制日志文件,配合-A时,会导致刷新多次数据库,在同一时刻执行转储和日志刷新,则应同时使用--flush-logs和-x,--master-data或-single-transaction,此时只刷新一次
建议:和-x,--master-data或 --single-transaction一起使用
--compact 去掉注释,适合调试,生产不使用
-d, --no-data 只备份表结构
-t, --no-create-info 只备份数据,不备份create table
-n,--no-create-db 不备份create database,可被-A或-B覆盖
--flush-privileges 备份mysql或相关时需要使用
-f, --force 忽略SQL错误,继续执行
--hex-blob 使用十六进制符号转储二进制列(例如,“abc”变为0x616263),受影响的数据类型包括BINARY, VARBINARY,BLOB,BIT
-q, --quick 不缓存查询,直接输出,加快备份速度(不使用查询缓存,备份的时候用查询缓存也没有意义)
例:备份所有数据库
mysqldump -A | gzip > /backup/all.sql.gz rm -rf /var/lib/mysql/* gzip -d all.sql.gz mysql < all.sql
例:备份所有数据库,一个库一个压缩文件
方法1:
for dbname in `mysql -e 'show databases' | grep -iEv 'database|schema'`; do mysqldump -B $dbname | gzip > /backup/$dbname.sql.gz;done方法2:生成分库备份脚本backup.sh
mysql -e 'show databases' | grep -iEv 'database|schema' | sed -r "s/(.*)/mysqldump -B \1 | gzip >\1-`date +%F`.sql/" > backup.sh
MyISAM备份选项:
支持温备;不支持热备,所以必须先锁定要备份的库,而后启动备份操作
锁定方法如下:
-x,--lock-all-tables:加全局读锁,锁定所有库的所有表,同时加--single-transaction或--lock-tables选项会关闭此选项功能
注意:数据量大时,可能会导致长时间无法并发访问数据库
-l,--lock-tables:对于需要备份的每个数据库,在启动备份之前分别锁定其所有表,默认为on,--skip-lock-tables选项可禁用,对备份MyISAM的多个库,可能会造成数据不一致
注:以上选项对InnoDB表一样生效,实现温备,但不推荐使用
InnoDB备份选项:
支持热备,可用温备但不建议用
--single-transaction
此选项Innodb中推荐使用,不适用MyISAM,此选项会开始备份前,先执行START TRANSACTION指令,并且在备份期间,不允许对数据进行修改操作
此选项和--lock-tables(此选项隐含提交挂起的事务)选项是相互排斥
备份大型表时,建议将--single-transaction选项和--quick结合一起使用
生产备份策略
InnoDB建议备份策略
mysqldump -uroot -A -F -E -R --single-transaction --master-data=1 \ --flush-privileges --triggers --hex-blob >$BACKUP_DIR/fullbak_$BACKUP_TIME.sqlMyISAM建议备份策略
mysqldump -uroot -A -F -E -R -x --master-data=1 --flush-privileges \ --triggers --hex-blob >$BACKUP_DIR/fullbak_$BACKUP_TIME.sql
例:生产中想实现自动备份的话,可写一个备份脚本,放在cron计划任务里,每天晚上2点执行
#!/bin/bash #FileName: mysqlbak.sh BACKUP_DIR=/backup/ BACKUP_TIME=`date +%F _%T` mysqldump -A -F -E -R --single-transaction --master-data=1 --flush-privileges \ --triggers --hex-blob > $BACKUP_DIR/fullbak_$BACKUP_TIME.sql
实验三:数据库数据文件损坏,如何还原最新状态?
前提:bin_log=on
数据库初始状态
1、全备份
mysqldump -A -F --single-transaction --master-data=2 \ > /backup/fullbak_`date +%F_%T`.sql2、修改数据库
create database db4; #新增两个数据库,模拟备份后的最新修改 create database db5;3、模拟数据库损坏
rm -rf /var/lib/mysql/* systemctl stop mariadb4、将备份文件及二进制日志拷到另一台机上
假设在实际工作中已经定期将全备份文件和二进制日志拷贝到另一台机上了 scp /backup/fullbak_2018-07-05_11\:15\:08.sql 目标主机:/backup/ less /backup/fullbak_2018-07-05_11 查看全备份文件,看以下这行-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000004', MASTER_LOG_POS=245;这行表示这个全备份文件备份到了二进制日志mysql-bin.000004的245的位置,那么mysql-bin.000004之前的二进制日志都可以不拷了,只用拷mysql-bin.000004以及之后的,本次只有mysql-bin.000004一个日志,所以只用拷mysql-bin.000004就行
scp /data/mysqllog/bin_log/mysql-bin.000004目标主机:/backup
5、在另一台机上还原数据库
确保另一台机是干净的,也没有重要数据 rm -rf /var/lib/mysql/* vim /etc/my.cnf skip-networking #加这一行 加防火墙规则或者拔网线也可以,总之禁止别人访问 systemctl restart mariadb mysql < /backup/fullbak_2018-07-05_11\:15\:08.sql #还原全备份文件 mysqlbinlog --start-position=245 /backup/mysql-bin.000004 > /backup/bin.sql mysql < /backup/bin.sql #还原最新的二进制日志 确认已还原至最新 mysql> show databases;
vim /etc/my.cnf skip-networking #删掉这一行 systemctl restart mariadb #重启数据库,以允许用户登录还原完成
实验四:误删除表,如何恢复最新状态?
前提:bin_log=on
1、周日做了全备份
mysqldump -A -F --single-transaction --master-data=2 \ > /backup/fullbak_`date +%F_%T`.sql2、周一10:00前修改数据
mysql> insert students values(26,'mysql',30,'M',2,3);(students表原本有25行)
3、周一10:00 有人误删除了一张表
drop table students;4、周一10:00-10:10 又修改数据库
insert teachers values(5,'mht',46,'m');周一10:10发现students表丢失
还原
1、mysql> flush tables with read lock; 加读锁
2、mysql> show master logs; 查看binlog的position 这里看到最新的日志是mysql-bin.0000043、mysql> flush logs; 生成新的二进制日志文件,旧日志文件就不会变化了
4、less /backup/full.sql 查看全备份的position,确定全备份到目前之间的所有日志文件及position 如:/data/mysqllog/bin_log/mysql-bin.000004 245
5、mysqlbinlog --start-position=245 /data/mysqllog/bin_log/mysql-bin.000004 > /backup/bin.sql #导出全备份到目前的二进制日志6、 vim /backup/bin.sql 找误删除的语句,删除此句
7、systemctl stop mariadb #停止数据库服务 rm -rf /var/lib/mysql/* #清空数据库 vim /etc/my.cnf skip-networking #加这一行 systemctl restart mariadb #启动数据库 mysql < /backup/ fullbak_2018-07-05_16\:13\:07.sql #还原全备份文件 mysql < /backup/bin.sql #还原最新的二进制日志确认数据库已还原至最新
vim /etc/my.cnf skip-networking #删掉这一行 systemctl restart mariadb #重启数据库,允许用户访问还原完成
小结
由此实验可以看出,二进制日志可以作为增量备份,每次先show master logs,然后flush logs,最后把目前跟上次备份之前的增量文件拷走就行
dump
xtrabackup
Percona
官网:www.percona.com
percona-server
InnoDB --> XtraDB
Xtrabackup
percona提供的mysql数据库备份工具,惟一开源的能够对innodb和xtradb数据库进行热备的工具
特点:
(1)备份还原过程快速、可靠
(2)备份过程不会打断正在执行的事务
(3)能够基于压缩等功能节约磁盘空间和流量
(4)自动实现备份检验
(5)开源,免费
xtrabackup
Xtrabackup2.2版之前包括4个可执行文件:
Innobackupex: perl 脚本
Xtrabackup: C/C++ 编译的二进制
Xbcrypt:加解密
Xbstream:支持并发写的流文件格式
xtrabackup 是用来备份 InnoDB 表的,不能备份非 InnoDB 表,和 mysqld server 没有交互
innobackupex 脚本用来备份非 InnoDB 表,同时会调用 xtrabackup 命令来备份 InnoDB 表,还会和 mysqld server 发送命令进行交互,如加读锁(FTWRL)、获取位点(SHOW SLAVE STATUS)等。即innobackupex是在 xtrabackup 之上做了一层封装实现的。
虽然目前一般不用 MyISAM 表,只是mysql 库下的系统表是 MyISAM 的,因此备份基本都通过 innobackupex 命令进行
Xtrabackup备份过程
Xtrabackup的新版变化
xtrabackup版本升级到2.4后,相比之前的2.1有了比较大的变化:innobackupex 功能全部集成到 xtrabackup 里面,只有一个 binary程序,另外为了兼容考虑,innobackupex作为 xtrabackup 的软链接,即xtrabackup现在支持非Innodb表备份,并且Innobackupex在下一版本中移除,建议通过xtrabackup替换innobackupex
xtrabackup安装:
yum install percona-xtrabackup 在EPEL源中
最新版本下载安装:
https://www.percona.com/downloads/XtraBackup/LATEST/
Xtrabackup用法
备份:innobackupex [option] BACKUP-ROOT-DIR
选项说明:
--user:该选项表示备份账号
--password:该选项表示备份的密码
--host:该选项表示备份数据库的地址
--databases:该选项接受的参数为数据名,如果要指定多个数据库,彼此间需要以空格隔开;如:"xtra_test dba_test",同时,在指定某数据库时,也可以只指定其中的某张表。如:"mydatabase.mytable"。该选项对innodb引擎表无效,还是会备份所有innodb表
--defaults-file:该选项指定了从哪个文件读取MySQL配置,必须放在命令行第一个选项的位置
--incremental:该选项表示创建一个增量备份,需要指定--incremental-basedir
--incremental-basedir:该选项表示接受了一个字符串参数指定含有full backup的目录为增量备份的base目录,与--incremental同时使用
--incremental-dir:该选项表示增量备份的目录
--include=name:指定表名,格式:databasename.tablename
Xtrabackup用法
Prepare:innobackupex --apply-log [option] BACKUP-DIR
选项说明:
--apply-log:一般情况下,在备份完成后,数据尚且不能用于恢复操作,因为备份的数据中可能会包含尚未提交的事务或已经提交但尚未同步至数据文件中的事务。因此,此时数据文件仍处理不一致状态。此选项作用是通过回滚未提交的事务及同步已经提交的事务至数据文件使数据文件处于一致性状态
--use-memory:该选项表示和--apply-log选项一起使用,prepare 备份的时候,xtrabackup做crash recovery分配的内存大小,单位字节。也可(1MB,1M,1G,1GB),推荐1G
--defaults-file:该选项指定了从哪个文件读取MySQL配置,必须放在命令行第一个选项的位置
--export:表示开启可导出单独的表之后再导入其他Mysql中
--redo-only:这个选项在prepare base full backup,往其中merge增量备份时候使用
Xtrabackup用法
还原:innobackupex --copy-back [选项] BACKUP-DIR
innobackupex --move-back [选项] [--defaults-group=GROUP-NAME] BACKUP-DIR
选项说明:
--copy-back:做数据恢复时将备份数据文件拷贝到MySQL服务器的datadir
--move-back:这个选项与--copy-back相似,唯一的区别是它不拷贝文件,而是移动文件到目的地。这个选项移除backup文件,用时候必须小心。使用场景:没有足够的磁盘空间同事保留数据文件和Backup副本
Xtrabackup用法
还原注意事项:
1.datadir目录必须为空。除非指定innobackupex --force-non-empty-directorires选项指定,否则--copy-backup选项不会覆盖
2.在restore之前,必须shutdown MySQL实例,你不能将一个运行中的实例restore到datadir目录中
3.由于文件属性会被保留,大部分情况下你需要在启动实例之前将文件的属主改为mysql,这些文件将属于创建备份的用户
chown -R mysql:mysql /data/mysql
以上需要在用户调用innobackupex之前完成
--force-non-empty-directories:指定该参数时候,使得innobackupex --copy-back或--move-back选项转移文件到非空目录,已存在的文件不会被覆盖。如果--copy-back和--move-back文件需要从备份目录拷贝一个在datadir已经存在的文件,会报错失败
备份生成的相关文件
使用innobakupex备份时,其会调用xtrabackup备份所有的InnoDB表,复制所有关于表结构定义的相关文件(.frm)、以及MyISAM、MERGE、CSV和ARCHIVE表的相关文件,同时还会备份触发器和数据库配置信息相关的文件。这些文件会被保存至一个以时间命名的目录中,在备份时,innobackupex还会在备份目录中创建如下文件:
(1)xtrabackup_info:innobackupex工具执行时的相关信息,包括版本,备份选项,备份时长,备份LSN,BINLOG的位置
(2)xtrabackup_checkpoints:备份类型(如完全或增量)、备份状态(如是否已经为prepared状态)和LSN(日志序列号)范围信息,每个InnoDB页(通常为16k大小)都会包含一个日志序列号,即LSN。LSN是整个数据库系统的系统版本号,每个页面相关的LSN能够表明此页面最近是如何发生改变的
(3)xtrabackup_binlog_info:MySQL服务器当前正在使用的二进制日志文件及至备份这一刻为止二进制日志事件的位置,可利用实现基于binlog的恢复
(4)backup-my.cnf:备份命令用到的配置选项信息
(5)xtrabackup_logfile:备份生成的日志文件
实验五: Xtrabackup完全备份及还原
原数据库状态
1、在原主机
innobackupex --user=root /backups #进行全备份scp -r /backups/2018-07-05_22-28-15/ 目标主机:/data/ #将备份文件拷到另一台机上2、在目标主机
innobackupex --apply-log /data/2018-07-05_22-28-15/ #整合完全备份可以看到多了两个事务日志文件
systemctl stop mariadb #停止mariadb服务 rm -rf /var/lib/mysql/* #清空数据库文件夹 innobackupex --copy-back /data/2018-07-05_22-28-15/ #还原数据库文件 chown -R mysql.mysql /var/lib/mysql/ #更改文件权限 systemctl start mariadb注:在目标主机的/etc/my.cnf配置中不要加innodb_log_group_home_dir选项(指定事务日志目录),否则数据库服务会启动不起来
确认还原成功
实验六: Xtrabackup完全,增量备份及还原
原主机状态
1、在原主机
innobackupex /backups #全备份 mkdir /backups/inc{1,2} #创建两个增量备份的目录 MariaDB [hellodb]> insert students values(26,'test1',18,'M',1,2);#模拟修改数据库
innobackupex --incremental /backups/inc1 --incremental-basedir=/backups/2018-07-05_23-36-56 #第一次增量备份 MariaDB [hellodb]> insert students values(27,'test2',28,'F',3,4);#模拟修改数据库
innobackupex --incremental /backups/inc2 --incremental-basedir=/backups/inc1/2018-07-05_23-38-47 #第二次增量备份此时/backup的目录结构
scp -r /backups/* 目标主机:/data/ #模拟拷贝到另一台主机
2、在目标主机
不启动mariadb rm -rf /var/lib/mysql/* #清空数据库目录 innobackupex --apply-log --redo-only /data/2018-07-05_23-36-56/ #整合完全备份 innobackupex --apply-log --redo-only /data/2018-07-05_23-36-56/ --incremental-dir=/data/inc1/2018-07-05_23-38-47 #整合第一次增量备份 innobackupex --apply-log --redo-only /data/2018-07-05_23-36-56/ --incremental-dir=/data/inc2/2018-07-05_23-43-07 #整合第二次增量备份 ls /var/lib/mysql/ innobackupex --copy-back /data/2018-07-05_23-36-56/ #还原数据库文件 chown -R mysql.mysql /var/lib/mysql/ #更改文件权限 systemctl start mariadb #启动数据库确认包括第一次修改和第二次修改在内的数据均已还原成功
实验七: Xtrabackup单表导出和导入
注:CentOS 7默认自带的mariadb-5.5版本是不支持单表操作的,此实验以比较新的mariadb-10.2.15版本为例,xtrabackup也需要装最新的2.4.11版
vim /etc/my.cnf innodb_file_per_table #配置文件中要设置每个表存放在单独的文件中初始的表信息
1、单表备份
innobackupex --include='hellodb.students' /backups2、备份表结构
mysql -e 'show create table hellodb.students' > student.sql vim students.sql 删除其中多余部分,留下下图所示内容3、模拟破坏表
mysql -e 'drop table hellodb.students'4、整合备份文件
innobackupex --apply-log --export /backups/2018-07-06_00-07-38/5、导入表结构
mysql hellodb < students.sql此时表结构已生成,但数据为空
6、删除表空间
mysql> alter table hellodb.students discard tablespace;7、复制相关文件
cp /backups/2018-07-06_00-07-38/hellodb/students.{cfg,exp,ibd} \ /var/lib/mysql/hellodb/ #复制相关文件到hellodb目录8、修改文件权限
chown -R mysql.mysql /var/lib/mysql/hellodb/ #修改hellodb下的文件权限9、导入表空间
mysql> alter table students import tablespace;确认students表已恢复