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备份与恢复的主要内容,如果未能解决你的问题,请参考以下文章

详解Mysql自动备份与恢复的几种方法(图文教

MySQL备份与恢复

Mysql备份与恢复

MySQL备份与恢复

MySQL备份与恢复

Mysql 备份恢复与 xtrabackup备份