MySQL备份与恢复
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL备份与恢复相关的知识,希望对你有一定的参考价值。
一、备份的目的
- 灾难恢复。发生灾难时,用于恢复损坏的数据
- 审计。数据库在过去某一个时间点是什么样的
- 测试。测试新功能是否可用
二、备份的分类
1.物理备份(physical backup)
直接复制数据文件,打包归档,不需要额外工具直接归档命令即可,但是跨平台能力比较差;如果数据量超过几十个G,则适用于物理备份
- 冷备(cold backup):服务器离线,读写操作都不能进行
- 温备(warm backup):服务器在线,全局施加共享锁,只能读不能写
- 热备(hot backup):数据库在线,备份的同时,读写照样进行
注:MyISAM不支持热备,InnoDB支持热备,但是需要专门的工具
2.逻辑备份(logical backup)
把数据抽取出来保存在sql脚本中,可以使用文本编辑器编辑,并且导入方便,直接读取sql语句即可;但逻辑备份恢复时间慢,占据空间大,无法保证浮点数的精度,并且恢复完数据库后需要重建索引
三、备份的方式
- 全量备份(full backup):备份mysql中所有的库和表,占用空间较大,是增量备份和差异备份的前提条件
- 增量备份(incremental backup):备份与上次全量、增量、差异备份后不同的数据内容,比较节约空间。备份数据少、备份速度快、恢复速度慢
- 差异备份(differential backup):备份从当前时间点到上次完整备份之间不同的数据内容,备份数据多、备份速度慢、恢复速度快
四、备份策略
1.备份需要考虑的因素
备份方式、备份实践、备份成本、锁时间、备份时长、性能开销、恢复成本、恢复时长、所能够容忍丢失的数据量
2.不同环境的解决方案
针对不同的场景下, 我们应该制定不同的备份策略对数据库进行备份, 一般情况下, 备份策略一般为以下三种
- 直接cp,tar复制数据库文件
- mysqldump+复制BIN LOGS
- vm2快照+复制BIN LOGS
- xtrabackup
(1)如果数据量较小,可以使用第一种方式,直接复制数据库文件
(2)如果数据量还行,可以使用第二种方式,先使用mysqldump对数据库进行完全备份,然后定期备份BINARY LOG达到增量备份的效果
(3)如果数据量一般,而又不过分影响业务运行,可以使用第三种方式,使用lvm2的快照对数据文件进行备份,而后定期备份BINARY LOG达到增量备份的效果
(4)如果数据量很大,而又不过分影响业务运行,可以使用第四种方式,使用xtrabackup进行完全备份后,定期使用xtrabackup进行增量备份或差异备份
3.备份的内容
- 数据库中的数据
- 数据库的配置文件
- mysql中的代码:存储过程,存储函数,触发器
- OS相关的配置文件,chrontab中的备份策略脚本
- 如果是主从复制的场景中,复制相关的信息
- 二进制日志文件需要定期备份,一旦发现二进制文件出现问题,需马上对数据进行完全备份
4.MySQL常用备份工具
- mysqldump:逻辑备份工具, 适用于所有的存储引擎, 支持温备、完全备份、部分备份、对于InnoDB存储引擎支持热备
- Xtrabackup(通常用innobackupex工具):强大的InnoDB/XtraDB热备工具, 支持完全备份、增量备份, 由percona提供,属物理备份,速度快
- lvm-snapshot:接近于热备的工具,因为要先请求全局锁,而后创建快照,并在创建快照完成后释放全局锁;很难实现增量备份,并且请求全局需要等待一段时间,在繁忙的服务器上尤其如此,几乎热备, 需借助文件系统管理工具进行备份
- mysqldumper:多线程的mysqldump
SELECT clause INTO OUTFILE ‘/path/to/somefile‘ LOAD DATA INFILE ‘/path/from/somefile‘ - mysqlhotcopy:接近冷备,基本没用,仅支持MyISAM存储引擎
- cp、tar等归档复制工具:物理备份工具, 适用于所有的存储引擎, 冷备、完全备份、部分备份
五、备份案例
1.使用tar或cp冷备份并恢复
(1)数据模拟
mysql -u root -p //登录MySQL
mysql>create database hiahia; //创建名为hiahia的数据库
mysql>create table hiahia.user (user_name char(12),user_phone char(11),primary key (user_phone));
//在hiahia库下创建user表,表中两个字段,其中user_phone为主键
mysql>insert into hiahia.user values (‘Zhangsan‘,‘2691376416‘);
mysql>insert into hiahia.user values (‘Lisi‘,‘2691376417‘);
mysql>select * from hiahia.user; //查看表中的数据
(2)备份与恢复【cp命令】
mysql>flush tables with read lock; //向所有表施加读锁,防止过程中有写入
mkdir /Backup/ //创建备份数据库存放目录
chown -R mysql:mysql /Backup/ //更改所有者及所有组
cp -a /usr/local/mysql/data/* /Backup/ //保留权限拷贝源数据文件.
rm -rf /usr/local/mysql/data/*????????????????? //删除数据库的所有文件,模拟故障
mysql -u root -p
mysql>select * from hiahia.user; //验证数据情况
cp -a /Backup/* /usr/local/mysql/data/ //将备份的数据文件拷贝回去
mysql -u root -p
mysql>select * from hiahia.user; //验证数据情况
(3)备份与恢复【tar命令】
mysql>flush tables with read lock; //向所有表施加读锁,防止过程中有写入
mkdir /Backup/ //创建备份数据库存放目录
chown -R mysql:mysql /Backup/ //更改所有者及所有组
cd /usr/local/mysql/data/ //进入MySQL数据存储目录
tar Jcvpf /Backup/mysql-$(date +%F).tar.xz ./*
//使用xz压缩当前目录下所有内容并将压缩文件放入/Backup目录,以日期取名文件
rm -rf /usr/local/mysql/data/* //删除数据库的所有文件,模拟故障
mysql -u root -p
mysql>select * from hiahia.user; //验证数据情况
tar -Jxvpf /Backup/mysql-2018-03-21.tar.xz -C /usr/local/mysql/data/
//通过tar备份文件恢复数据到/usr/local/mysql/data/目录下
mysql -u root -p
mysql>select * from hiahia.user; //验证数据情况
2.使用mysqldump全量备份恢复
(1)数据模拟
mysql -u root -p //登录MySQL
mysql>create database hiahia; //创建名为hiahia的数据库
mysql>create table hiahia.user (user_name char(12),user_phone char(11),primary key (user_phone));
//在hiahia库下创建user表,表中两个字段,其中user_phone为主键
mysql>insert into hiahia.user values (‘Zhangsan‘,‘2691376416‘);
mysql>insert into hiahia.user values (‘Lisi‘,‘2691376417‘);
mysql>select * from hiahia.user; //查看表中的数据
(2)mysqldump全量备份
mkdir /Backup/ //创建备份数据库存放目录
chown -R mysql:mysql /Backup/ //更改所有者及所有组
(2.1)备份库
mysqldump -u 用户名 -p 密码 数据库名 >/备份路径/备份文件名
mysqldump -u root -p hiahia >/Backup/hiahia-$(date +%F).sql
//备份hiahia库,并将导出的sql语句文件重定向导出到/Backup目录下
(2.2)备份库下的表
mysqldump -u 用户名 -p 密码 数据库名 表名 >/备份路径/备份文件名
mysqldump -u root -p hiahia user >/Backup/hiahia-user-$(date +%F).sql
//备份hiahia库下的user表,并将导出的sql语句文件重定向导出到/Backup目录下
(2.3)备份多个库
mysqldump -u 用户名 -p 密码 --databases 库名1 [库名2] ... >/备份路径/备份文件名
mysqldump -u root -p --databases hiahia mysql >/Backup/hiahia-mysql-$(date +%F).sql
//备份hiahia、mysql两个库,并将导出的sql语句文件重定向导出到/Backup目录下
(2.4)备份整个库
mysqldump -u 用户名 -p 密码 --all-databases >/备份路径/备份文件名
mysqldump -u root -p --all-databases >/Backup/all-$(date +%F).sql
//将这个MySQL库备份,并将导出的sql语句文件重定向导出到/Backup目录下
(2.5)备份表结构
mysqldump -u 用户名 -p [密码] -d 数据库名 表名 >/备份路径/备份文件名
mysqldump -u root -p -d hiahia user >/Backup/hiahia-desc-user-$(date +%F).sql
//只备份hiahia库下user表的结构(即表的头部),并将导出的sql语句文件重定向导出到/Backup目录下
(3)mysqldump全量恢复
(3.1)使用source恢复
-
登录MySQL数据库
- 执行source 备份sql脚本文件路径
(3.2)使用mysql命令恢复
mysql -u root -p [密码] </库备份脚本路径
(3.3)恢复表
mysql -u root -p //登录MySQL数据库,密码为123
mysql>drop table hiahia.user; //删除user表,模拟表故障
mysql>select * from hiahia.user; //验证数据情况
mysql>use hiahia; //进入要恢复的库
mysql>source /Backup/hiahia-user-2018-03-21.sql
//通过备份的表sql文件恢复数据
mysql>select * from hiahia.user; //验证数据情况
(3.4)恢复库
mysql -u root -p //登录MySQL数据库,密码为123
mysql>drop database hiahia; //删除hiahia库,模拟库故障
mysql>show databases; //验证数据情况
注:使用mysql恢复库时,如库已不存在,需自行创建同名库,再通过备份库文件恢复,并且在恢复时需指定恢复到哪个库
mysql -u root -p //登录MySQL数据库,密码为123
mysql>create database hiahia; //创建库
mysql -u root -p hiahia </Backup/hiahia-2018-03-21.sql
//通过备份库sql文件恢复库数据到hiahia库下
mysql -u root -p //登录MySQL数据库,密码为123
mysql>show databases; //验证数据情况
六、MySQL增量备份与恢复
mysqldump完全备份的缺点:备份数据中有重复数据、备份时间与恢复时间长
1.增量备份
备份自上一次备份之后增加或变化的文件或者内容
特点
- 重复数据,备份量不大,时间短
- 但恢复麻烦,需要上次完整备份及完整备份之后所有的增量备份才能恢复,而且要对所有增量备份进行逐个反推恢复
- 但MySQL中并未直接提供增量备份方法,但可通过MySQL提供的二进制日志(Binary logs)间接实现增量备份
2.二进制日志
- 保存所有更新数据库的操作
- MySQL启动后便开始记录,当达到max_binlog_size选项值后或收到flush logs命令后自动重新创建新的日志文件
- 因此只需定时执行flush logs命令,再将新生成日志文件保存到安全位置,即可完成这一时间段增量备份
3.案例:MySQL增量备份
(1)数据模拟
mysql -u root -p //登录MySQL
mysql>create database hiahia; //创建名为hiahia的数据库
mysql>create table hiahia.user (user_name char(12),user_phone char(11),primary key (user_phone));
//在hiahia库下创建user表,表中两个字段,其中user_phone为主键
mysql>insert into hiahia.user values (‘Zhangsan‘,‘2691376416‘);
mysql>insert into hiahia.user values (‘Lisi‘,‘2691376417‘);
mysql>select * from hiahia.user; //查看表中的数据
(2)开启MySQL二进制日志
-
方式一:编辑my.cnf配置文件在[mysqld]项下加入log-bin=filepath,重启mysqld服务即可(默认即为开启)
- 方式二:运行"mysqld --log-bin=filepath",然后重启mysqld服务
注:filepath为二进制文件存储路径,如不指定路径只指定名称,默认存储在数据目录下(源码默认:/usr/local/mysql/data/;rpm/yum:/var/lib/mysql)
(3)完整备份
增量备份前,必须有完整备份才可以
mysqldump -u root -p hiahia user >/Backup/hiahia-user-$(date +%F).sql
//备份hiahia库下的user表,并将导出的sql语句文件重定向导出到/Backup目录下
(4)增量备份
mkdir /Backup/ //创建备份数据库存放目录
chown -R mysql:mysql /Backup/ //更改所有者及所有组
ls -l /usr/local/mysql/data/
//增量备份前,查询原二进制日志文件名,以便区分新旧二进制日志文件
mysql -u root -p //登录MySQL,密码为123
mysql>flush logs; //生成新的二进制日志,下面操作全部记录到新日志文件中,方便增量备份
mysql>insert into hiahia.user values (‘hehe‘,‘13452231231‘);
//模拟数据更改
mysql> insert into hiahia.user values (‘haha‘,‘13456223123‘);
mysql>insert into hiahia.user values (‘huohuo‘,‘12345621231‘);
mysql>insert into hiahia.user values (‘heihei‘,‘136741234312‘);
mysqladmin -u root -p flush-logs
//通过命令,再次生成新的日志文件,以便将新增数据记录日志截取为独立的日志文件
ls -l /usr/local/mysql/data/
//查询新增二进制日志文件,新增日志文件里即记录新增量数据情况
mysqlbinlog /usr/local/mysql/data/mysql-bin.000005
//使用mysqlbinlog命令查看新记录二进制日志内容
注:如mysqlbinlog查看时出现"unknown variable ....",可以使用mysqlbinlog --no-defaults 二进制日志文件,该方式查看
cp /usr/local/mysql/data/mysql-bin.000005 /Backup/
4.案例:MySQL增量恢复
增量恢复场景
- 人为SQL语句破坏数据库
- 在下次全量备份前发生系统故障导致数据库数据丢失
- 主从架构中,主库数据发生故障
数据丢失分类
- 只丢失完全备份之后的数据
- 包括完整备份在内的所有数据
(1)只丢失完全备份之后的数据(恢复过程)
mysqladmin -u root -p flush-logs
//生成新的二进制日志,避免恢复时将所有的操作都记录,导致数据出错(建议备份前和恢复前都输入一次)
mysqlbinlog 二进制日志文件 | mysql -u root -p
//将二进制增量文件逐个推倒恢复数据库,直到恢复到完整备份时刻
(2)包括完整备份在内的所有数据(恢复过程)
mysqladmin -u root -p flush-logs
//生成新的二进制日志,避免恢复时将所有的操作都记录,导致数据出错(建议备份前和恢复前都输入一次)
mysql -u root -p 数据库名 </库备份脚本路径.
//恢复完整备份数据
mysqlbinlog 二进制日志文件 | mysql -u root -p
(3)基于时间点与位置的恢复
默认增量恢复是恢复整个二进制日志中内容,当然也可以利用二进制日志实现基于某个时间点及位置的恢复,达到精确恢复
(3.1)基于时间点恢复
指定导入停止时间点,可只恢复到该时间点前面数据,从而跳过某个发生错误的时间点实现数据恢复;也可指定导入开始时间点,从该时间点到日志文件结尾全部导入
mysqlbinlog --stop-datetime=‘日期 时间‘ 二进制日志文件 | mysql -u root -p
mysqlbinlog --start-datetime=‘日期 时间‘ 二进制日志文件 | mysql -u root -p
(3.2)基于位置恢复
如采用基于时间点恢复,可能出现某个时间点既同时存在正确操作又存在错误操作的情况,因此基于位置的恢复可以更好的控制
每个操作都会记录一个end_log_pos值,使用基于位置恢复可以基于某条语句恢复
mysqlbinlog --stop-position=‘end_log_pos‘ 二进制日志文件 | mysql -u root -p
mysqlbinlog --start-position=‘end_log_pos‘ 二进制日志文件 | mysql -u root -p
5.案例:MySQL增量恢复(丢失完全备份后)
(1)丢失完全备份之后的数据
mysql -u root -p //登录MySQL,密码为123
mysql>delete from hiahia.user where user_name=‘hehe‘;
//模拟增量数据丢失
mysql>delete from hiahia.user where user_name=‘haha‘;
mysql> delete from hiahia.user where user_name=‘huohuo‘;
mysql>delete from hiahia.user where user_name=‘heihei‘;
mysql>select * from hiahia.user; //验证数据情况
mysqladmin -u root -p flush-logs //生成新的二进制日志
mysqlbinlog /Backup/mysql-bin.000005 | mysql -u root -p
//通过备份的增量二进制日志文件恢复增量数据,如有多个增量日志文件逐个恢复
mysql -u root -p //登录MySQL,密码为123
mysql>select * from hiahia.user; //验证数据情况
(2)丢失完整备份在内数据
mysql -u root -p //登录MySQL,密码为123
mysql>drop table hiahia.user; //删除user表,模拟表故障
mysql>select * from hiahia.user; //验证数据情况
mysql>mysql -u root -p hiahia </Backup/hiahia-user-2018-03-21.sql
//通过备份表sql文件恢复表数据到hiahia库下
mysql -u root -p //登录MySQL,密码为123
mysql>select * from hiahia.user; //验证数据情况,完整备份恢复
mysqladmin -u root -p flush-logs //生成新的二进制日志
mysqlbinlog /Backup/mysql-bin.000005 | mysql -u root -p
//通过备份的增量二进制日志文件恢复增量数据,如有多个增量日志文件逐个恢复
mysql -u root -p //登录MySQL,密码为123
mysql>select * from hiahia.user; //验证数据情况
(3)基于时间点恢复
mysql -u root -p //登录MySQL,密码为123
mysql>delete from hiahia.user where user_name=‘hehe‘;
//模拟增量数据丢失
mysql>delete from hiahia.user where user_name=‘haha‘;
mysql> delete from hiahia.user where user_name=‘huohuo‘;
mysql>delete from hiahia.user where user_name=‘heihei‘;
mysql>select * from hiahia.user; //验证数据情况
mysqladmin -u root -p flush-logs //生成新的二进制日志
mysqlbinlog /Backup/mysql-bin.000005
//通过查看二进制日志确认恢复时间点,如该处为"180321 19:58:40"
mysqlbinlog /Backup/mysql-bin.000005 --stop-datetime=‘2018-03-21 19:58:40‘ | mysql -u root -p
//只恢复‘2018-03-21 19:58:40‘之前数据
mysql -u root -p //登录MySQL,密码为123
mysql>select * from hiahia.user; //验证数据情况
mysqlbinlog /Backup/mysql-bin.000005
//通过查看二进制日志确认恢复时间点,如该处为从"180321 19:58:45"
mysqlbinlog /Backup/mysql-bin.000005 --start-datetime=‘2018-03-21 19:58:45‘ | mysql -u root -p
//只恢复‘2018-03-21 19:58:45‘之后数据
mysql -u root -p //登录MySQL,密码为123
mysql>select * from hiahia.user; //验证数据情况
注:"stop-datetime或start-datetime"不要相同时间点导入多次,会重复性导入
(4)基于位置恢复
mysql -u root -p //登录MySQL,密码为123
mysql>delete from hiahia.user where user_name=‘hehe‘;
//模拟增量数据丢失
mysql>delete from hiahia.user where user_name=‘haha‘;
mysql> delete from hiahia.user where user_name=‘huohuo‘;
mysql>delete from hiahia.user where user_name=‘heihei‘;
mysql>select * from hiahia.user; //验证数据情况
mysqladmin -u root -p flush-logs //生成新的二进制日志
mysqlbinlog /Backup/mysql-bin.000005
//通过查看二进制日志确认恢复pos,如该处为从"577"
mysqlbinlog /Backup/mysql-bin.000005 --stop-position=‘577‘ | mysql -u root -p
//只恢复‘577‘之前数据
mysql -u root -p //登录MySQL,密码为123
mysql>select * from hiahia.user; //验证数据情况
mysqlbinlog /Backup/mysql-bin.000005
//通过查看二进制日志确认恢复时间点,如该处为从"718"
mysqlbinlog /Backup/mysql-bin.000005 --start-position=‘718‘ | mysql -u root -p
//只恢复‘718‘之后数据
mysql -u root -p //登录MySQL,密码为123
mysql>select * from hiahia.user; //验证数据情况
以上是关于MySQL备份与恢复的主要内容,如果未能解决你的问题,请参考以下文章