天天看点

MySQL深入09-备份-恢复

备份的目的

  • 灾难恢复;
  • 数据审计;
  • 测试;

备份类型

根据备份时,数据库服务器是否在线:

  • 冷备:cold backup
  • 温备:warm backup,全局施加共享锁,允许读,禁止写
  • 热备:hot backup

根据备份的数据集:

  • 完全备份:full backup
  • 部分备份:partial backup

根据备份时的接口:是直接备份数据文件还是通过mysql服务器导出数据

  • 物理备份:直接复制(或打包归档)数据文件的备份方式,physical backup
    • 优点: 无需额外工具,直接copy即可;恢复直接复制备份文件即可
    • 缺点:与存储引擎有关,跨平台能力较弱
  • 逻辑备份:把数据从库中提取出来,并保存为文本文件,logical backup,工具是mysqldump
    • 优点: 能使用编辑器处理;恢复简单;能基于网络恢复;有助于避免数据损坏
    • 缺点: 备份文件较大,备份较慢;无法保证浮点数的精度;使用逻辑备份数据恢复后,还需手动重建索引,十分消耗CPU资源

根据备份时的数据变化方式:

  • 增量备份:incremental backup,节约空间;对上次完全备份或增量备份后变化的数据进行备份
  • 差异备份:differential backup,容易恢复;对上次完全备份后的差异数据进行备份

备份策略

  • 选择合适的备份方式;
  • 选择备份时间;
  • 考虑到恢复成本(主要是恢复时长);
  • 考虑备份成本(包括 锁时间,备份时长,备份负载等);
  • 备份的难度取决于所能容忍的数据丢失量;

备份对象

  • 数据文件;
  • 代码:存储过程,存储函数,触发器等;
  • OS相关的配置文件,如crontab配置计划及相关脚本;
  • 跟复制相关的配置信息
  • 二进制日志文件;

备份工具

mysqldump:逻辑备份工具

  • InnoDB热备、MyISAM温备、Aria温备;
  • 单线程备份工具;

mysqldumper:多线程的mysqldump

  • 很难实现差异或增量备份

lvm-snapshot:

  • 实现接近于热备的工具,因为要先请求全局锁,而后创建快照,并在创建快照完成后释放全局锁;
  • 使用cp,tar等工具进行物理备份;
  • 备份和恢复速度都较快;
  • 很难实现增量备份,并且请求全局锁需要等待一段时间,在繁忙的服务器上尤其如此;

命令行下的部分备份数据工具

  • 备份:select clause into outfile ‘/path/to/somefile’
  • 恢复:load data infile ‘/path/from/somefile’
  • 不会备份关系定义,仅备份表中的数据
  • 逻辑备份工具,快于mysqldump

innobackup:商业备份工具,Innobase

Xtrabackup:由Percona提供的开源备份工具

  • InnoDB热备:增量备份;
  • MyISAM温备:不支持增量备份;
  • 物理备份,速度快;

mysqlhotcopy:是一个Perl脚本

  • 只能用于备份MyISAM库,且数据恢复需要重启mysql,故基本可认为是冷备;

mysqldump

适用场景:建议备份数据在5G以下,数据超过10G不建议使用此工具

用法:mysqldump [options] [db_name [tbl_name…]]

  • 备份单个库:mysqldump [options] db_name
    • 备份时,不创建库,只备份库中的表;
    • 故恢复时,若目标库不存在,则需要事先手动创建数据库;
  • 备份多个库:--databases db1,db2
    • --databases db1 # 备份单库时建议使用,这样备份时也能备份库,在恢复时无需新建数据库;

其它备份选项:

--all-databases # 备份所有库;
--lock-all-tables # 请求锁定所有表后再备份,对MyISAM、InnoDB、Aria做温备;
--single-transaction # 能够对InnoDB存储引擎实现热备;
--events # 备份事件调度器代码;
--routines # 备份存储过程和存储函数;
--triggers # 备份触发器;
--flush-logs # 备份前,请求到锁后先滚动日志再备份
--master-data=[0|1|2] # 记录复制时二进制日志的同步位置
0:不记录;
1:记录CHANGE MASTER语;
2:记录为注释的CHANGE MASTER语句;      

备份步骤

  1. 请求锁:--lock-all-tables或--single-transaction进行innodb热备;
  2. 滚动日志:--flush-logs;
  3. 选定要备份的库:--databases;
  4. 记录二进制日志文件及位置:--master-data=2;
  5. 3种备份方法:
    # 手动锁表,手动滚动日志:
    mysql> flush tables with read lock;
    mysql> flush logs;
    mysqldump --databases hdb > hdb1.sql
    mysql> unlock tables;
    # 对MyISAM温备:
    mysqldump --databases hdb --lock-all-tables --flush-logs --master-data=2 > hdb.sql
    # 对InnoDB热备:
    mysqldump --databases hdb --single-transaction --flush-logs --master-data=2 > hdb.sql      

数据恢复步骤

  1. 建议先关闭二进制日志(log_bin=OFF),并关闭其它用户连接;
  2. 导入数据即可完成数据恢复:mysql < hdb.sql

基于mysqldump的备份策略

  • 备份:mysqldump+二进制日志文件
    • 周日做一次完全备份:备份的同时滚动日志
    • 周一至周六:备份二进制日志
  • 恢复:
    • 完全备份数据+每天的二进制日志文件

注:对于MySQL配置文件,以及与MySQL相关的OS配置文件在每次修改后都应该直接进行备份

lvm-snapshot

使用场景

  • 基于LVM快照的备份方式,故事务日志和数据文件必须在同一个卷上;
  • 创建快照卷之前,要请求MySQL的全局锁;在快照创建完成后释放锁;
  • 请求全局锁完成之后,做一次日志滚动;并做二进制日志文件及位置标记;
# 请求全局锁,并滚动日志
mysql> flush tables with read lock;
mysql> flush logs;
# 做二进制日志文件及位置标记(手动进行)
mysql -e ‘show master status’ > /backups/bin.pos
# 创建快照卷
lvcreate -s -L 100M -n /dev/myvg/mydata-snap -p r /dev/myvg/mydata
# 释放全局锁
mysql> unlock tables;
# 挂载快照卷并备份
mount /dev/myvg/mydata-snap /mnt -o ro
cp -a /mnt/data/ /backups/data/2014-04-11
# 备份完成之后,删除快照卷      
# 还原数据,修改权限及属主属组等,并启动mysql
cp -a /backups/data/2014-04-11/* /mydata/data/
# 提取备份之后的所有事件至某sql脚本中,并做即时点还原
cat /backups/bin.pos
mysqlbinlog --start-position=# --stop-position=# mysql-bin.# > bak.sql
mysql < bak.sql      

mylvmbackup:是一个perl脚本,能够实现基于LVM的快速备份MySQL数据文件,对于上面介绍的备份操作可实现自动化一键完成

  • 官方地址是:http://www.lenzg.net/mylvmbackup/
  • 需要安装的Perl5模块有:DBI、DBD:mysql、Config::IniFiles、TimeDate、File::Copy::Recursive、Sys::Syslog、MIME::Lite
    • 可通过cpan自动安装,如 cpan Config::IniFiles
  • 安装后,稍微配置一下其配置文件/etc/mylvmbackup.conf即可,然后执行mylvmbackup命令即可完成基于LVM的数据备份过程了;

Xtrabackup

适用场景:由percona提供的mysql数据库备份工具,能够实现对innodb和xtradb数据库进行在线热备;

特点:

  • 备份过程快速、可靠;
  • 备份过程不会打断正在执行的事务;
  • 能够基于压缩等功能节约磁盘空间和流量;
  • 自动实现备份检验;
  • 还原速度快;

安装:

yum --nogpgcheck localinstall percona-xtrabackup-2.1.8-733.rhel6.x86_64.rpm # 备份工具包
yum --nogpgcheck localinstall percona-toolkit-2.2.4-1.noarch.rpm # 包含众多pt-*工具,可完整数据一致性检测,表数据同步等功能
percona-xtrabackup包中包含的2个工具:
xtrabackup # 是用于热备份innodb, xtradb表中数据的工具,不能备份其他类型的表,也不能备份数据表结构;
innobackupex # 是将xtrabackup进行封装的perl脚本,提供了备份myisam表的能力      

备份步骤:

完全备份:

innobackupex --user=root --password=magedu /data/backups/ # 只需指定备份文件所在目录即可
# 如果要使用一个最小权限的用户进行备份,则可基于如下命令创建此类用户:
mysql> create user ’bkuser’@’localhost’ identified by ’bkpass’;
mysql> revoke all privileges,grant option from 'bkuser';
mysql> grant reload,lock tables,replication client on *.* to 'bkuser'@'localhost';
mysql> flush privileges;
# 使用innobakupex备份时,其会调用xtrabackup备份所有的InnoDB表,复制所有关于表结构定义的相关文件(.frm)、以及MyISAM、MERGE、CSV和ARCHIVE表的相关文件,同时还会备份触发器和数据库配置信息相关的文件。这些文件会被保存至一个以时间命令的目录(如2014-04-23_17-34-45)中;
# 在备份的同时,innobackupex还会在备份目录中创建如下文件:
xtrabackup_checkpoints # 备份类型(如完全或增量)、备份状态(如是否已经为prepared状态)和LSN(日志序列号)范围信息;
xtrabackup_binlog_info  # mysql服务器当前正在使用的二进制日志文件及至备份这一刻为止二进制日志事件的位置;
xtrabackup_binary # 备份中用到的xtrabackup的可执行文件;
backup-my.cnf # 备份命令用到的配置选项信息;      

增量备份:

  • 每个InnoDB的页面都会包含一个LSN信息,每当相关的数据发生改变,相关的页面的LSN就会自动增长。这正是InnoDB表可以进行增量备份的基础,即innobackupex通过备份上次完全备份之后发生改变的页面来实现;
    innobackupex --incremental /data/backups/ --incremental-basedir=/data/backups/2014-04-23_17-44-51/ # 还需指定需做增量备份的完全备份的目录路径      
  • innobackupex命令会在/data/backups/目录中创建一个新的以时间命名的目录以存放所有的增量备份数据。另外,在执行过增量备份之后再一次进行增量备份时,其--incremental-basedir应该指向上一次的增量备份所在的目录;
  • 注:增量备份仅能应用于InnoDB或XtraDB表,对于MyISAM表而言,执行增量备份时其实进行的是完全备份;

数据恢复步骤:分准备和恢复两个阶段进行

准备阶段:

 一般情况下,在备份完成后,数据尚且不能用于恢复操作,因为备份的数据中可能会包含尚未提交的事务或已经提交但尚未同步至数据文件中的事务。因此,此时数据文件仍处理不一致状态。“准备”的主要作用正是通过回滚未提交的事务及同步已经提交的事务至数据文件也使得数据文件处于一致性状态;

完全备份准备:

innobackupex --apply-log /data/backups/2014-04-23_17-34-45 # 使用apply-log选项,并指定需“准备”的备份目录即可      

增量备份准备:

innobackupex --apply-log --redo-only /data/backups/2014-04-23_17-44-51 # 首先对完全备份目录进行“准备”
innobackupex --apply-log --redo-only /data/backups/2014-04-23_19-48-27 # 然后对第一次增量备份目录进行“准备”
innobackupex --apply-log --redo-only /data/backups/2014-04-23_19-56-26 # 然后对第二次增量备份目录进行“准备”      

注:在实现“准备”的过程中,innobackupex通常还可以使用--use-memory选项来指定其可以使用的内存的大小,默认通常为100M。如果有足够的内存可用,可以多划分一些内存给prepare的过程,以提高其完成速度;

增量备份的“准备”阶段与完全备份的“准备”阶段略有不同:

  • 需要在每个备份(包括完全和各个增量备份)上,将已经提交的事务进行“重放”;“重放”之后,所有的备份数据将合并到完全备份上;
  • 基于所有的备份将未提交的事务进行“回滚”;

恢复阶段:

innobackupex --copy-back /data/backups/2014-04-23_17-34-45 # 完全备份恢复数据;若有增量备份,则需完成准备阶段后,再利用完全备份目录进行数据恢复
chown -R mysql:mysql /data/mysqldata/ # 当数据恢复至DATADIR目录以后,还需要修改数据文件的属主和属组,如mysql
service mysqld start # 启动mysql即可,数据恢复完成      

总结:以上介绍的MySQL数据备份方式是最常见的3种方式,最强大的当然是Xtrabackup(毕竟人家可以热备份嘛),但需提前安装备份工具;而在测试环境,使用mysqldump也不失为一种快捷的方式;若MySQL的数据文件是位于LVM磁盘上,且数据文件较大,则也可考虑利用lvm-snapshot方式;

数据备份准则:

  • 将数据和备份放在不同的磁盘设备上,异地或异机备份存储较为理想;
  • 备份的数据应该周期性地进行还原测试;
  • 每次灾难恢复后都应该立即做一次完全备份;
  • 针对不同规模或级别的数据量,要制定好备份策略;
  • 二进制日志应该跟数据文件在不同磁盘上,并周期性地备份好二进制日志文件;

从备份中恢复数据应该遵循的步骤:

  • 停止MySQL服务器;
  • 记录服务器的配置和文件权限;
  • 将数据从备份移到MySQL数据目录,其执行方式依赖于工具,如innobackupex --copy-back;
  • 改变配置和文件权限;
  • 以限制访问模式重启服务器:
    • skip-networking # 此选项可使MySQL跳过网络功能
    • socket=/tmp/mysql-recovery.sock
    • 方法:编辑my.cnf配置文件,添加如下项:
  • 载入逻辑备份(如果有);检查和重放二进制日志;
  • 检查已经还原的数据是否可用;
  • 重新以完全访问模式重启服务器;
  • 注释前面在my.cnf中添加的选项即可,并重启MySQL;

其它可参考备份方式:

Xtrabackup的“流”及“备份压缩”功能

Xtrabackup对备份的数据文件支持“流”功能,即可以将备份的数据通过STDOUT传输给tar程序进行归档,而不是默认的直接保存至某备份目录中。要使用此功能,仅需要使用--stream选项即可:

innobackupex --stream=tar /data/backups | gzip > /data/backups/`date +%F_%H-%M-%S`.tar.gz # 归档并压缩后保存在本地
innobackupex --stream=tar /data/backups | ssh [email protected] "cat - > /backups/`date +%F_%H-%M-%S`.tar" # 归档保存在远程主机,
innobackupex --parallel=2  /data/backups # 在执行本地备份时,可以使用--parallel指定在复制时启动的线程数目,实现多个文件的并行复制;      

注:将备份数据保存至远程主机时,需保证可通过ssh直接登录远程主机而无需密码,即需进行ssh授权

Xtrabackup导入或导出单张表

默认情况下,InnoDB表不能通过直接复制表文件的方式在mysql服务器之间进行移植;

而使用Xtrabackup工具可以实现此种功能,不过,此时需要“导出”表的mysql服务器启用了innodb_file_per_table选项,并且“导入”表的服务器同时启用了innodb_file_per_table和innodb_expand_import选项;

导出表

导出表是在备份的准备阶段(prepare)进行的,因此,一旦完全备份完成,就可以在prepare过程中通过--export选项将某表导出了:

innobackupex --apply-log --export /path/to/backup # 此命令会为每个innodb表的表空间创建一个以.exp结尾的文件,这些以.exp结尾的文件则可以用于导入至其它服务器;      

导入表

要在mysql服务器上导入来自于其它服务器的某innodb表,需要先在当前服务器上创建一个跟原表表结构一致的表,而后才能实现将表导入:

mysql> CREATE TABLE mytable (...)  ENGINE=InnoDB;
# 然后将此表的表空间删除:
mysql> ALTER TABLE mydatabase.mytable  DISCARD TABLESPACE;
# 接下来,将来自于“导出”表的服务器的mytable表的mytable.ibd和mytable.exp文件复制到当前服务器的数据目录,然后使用如下命令将其“导入”:
mysql> ALTER TABLE mydatabase.mytable  IMPORT TABLESPACE;      

上一篇:MySQL深入08-日志及其参数设定