使用 mysqldump, lvm snapshot 和 Xtrabackup 对mysql 进行备份

实验环境准备:
 1、首先,创建一个LV /dev/myvg/lv1, 挂载至 /mydata, 创建/mydata/data目录 作为mysql的数据目录,安装mysql。
 2、编辑mysql的配置文件 /etc/my.cnf, 添加或修改设置如下
 innodb_file_per_table=1  #启用InnoDB表每表一文件,默认所有库使用一个表空间,这个在单表备份和恢复中是必须的,而且也便于管理,建议开启
 log-bin=/mylog/mysql-bin #缺省二进制日志文件是和数据文件放在一起的,出于安全和便于管理的考虑,应该分开存放。

 3、启动mysqld服务,创建测试数据库如下:
 mysql> create database mydb;
 mysql> use mydb;
 mysql> create table tb1 (id tinyint unsigned auto_increment,province char(30) not null, capital char(30),primary key (id));
 mysql> insert into tb1 (province, capital) values ("xinjiang", "wulumuqi"), ("hubei", "wuhan"),("guangdong", "guangzhou");

 


一、使用 mysqldump进行备份。
 1、检查当前二进制日志滚动到那个位置

mysql> show master status;
+------------------+----------+--------------+------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000003 |      806 |              |                  |
+------------------+----------+--------------+------------------+

 到二进制日志目录查看当前最新的二进制日志文件名,确实是 mysql-bin.000003
 2、备份数据库至 /bak 目录 (注意mysql用户应当有读取该目录中文件的权限)
 # mysqldump -uroot -p --single-transaction --flush-logs --all-databases --master-data=2 --triggers --events --routines > /bak/alldb_$(date "+%Y%m%d%H%m").sql
 这里使用 --single-transaction 会自动锁定所有表,所以不用单独指定 --lock-all-tables.确保备份过程中的数据的一致性,
 --flush-logs 让日志滚动一次
 --master-data=2 在输出中记录当前二进制日志的postion,但是被注释掉。值为1则不会被注释,用于主从复制。
 记录备份那一刻二进制日志的位置,在采用备份恢复数据之后,需要采用二进制日志从该位置开始恢复数据至最新的状态。使用 --master-data=2 比备份之前执行 show master 

status 记录二进制日志文件位置更方便且精确。当然,既然滚动了日志,其实只要记下来备份之前的二进制日志文件名和备份之后的二进制日志文件名就可以了。

 注意,这里只备份了数据,二进制日志也是需要备份的。而且二进制日志的备份格外重要,因为如果二进制日志保存完整,数据就可以完全恢复,反之如果做了备份,二进制日志却

丢了,则从最新的一次数据备份之后的数据更新就会丢失。由于这里只是实验,二进制日志已经和数据目录不在同一文件系统就够了。实际生产环境下,二进制日志备份当然不应只在数据库

服务器本地磁盘上做备份啦。 
 另:做实验的时候最好也把二进制日志文件备份出来比较好,只是为了挪个位置,因为重新初始化的时候也会写二进制日志的,免得搞混。

 3、检查最新二进制日志文件名,确认二进制日志已经滚动
mysql> show master status;
+------------------+----------+--------------+------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000004 |      107 |              |                  |
+------------------+----------+--------------+------------------+


 4、进一步更新数据库
 mysql> use mydb;
 mysql> create table distro (id tinyint unsigned auto_increment, distroname char (30), vendor char (30), primary key (id));
 mysql> insert into distro (distroname, vendor) values ("rhel", "redhat"), ("gentoo", "gentoo.org");

 5、模拟数据库损坏、崩溃
 # rm -rf /mydata/data/*

 6、重新初始化数据库,这样mysqld 服务才能重新正常启动。启动的时候或许需要使用 skip-networking 选项禁止网络连接,在实际生产环境中,可能需要避免在恢复之前客户端的

连接
 关闭二进制日志记录,避免恢复过程也记录进二进制日志。
 mysql> set global sql_log_bin=0;
 mysql> set session sql_log_bin=0;
 检查变量是否修改成功
 mysql> select @@global.sql_log_bin;
 mysql> select @@session.sql_log_bin;
 根据情况修改会话变量或者系统变量

 7、将之前备份的 sql 文件导入数据库
 有两种方法:
 a. mysql < /bak/alldb_201309082209.sql  #直接执行 mysql 命令读取sql脚本重新创建数据库
 b. mysql> source /bak/alldb #连接mysql服务器后source 备份产生的sql脚本
 由于数据库是重新初始化的,所以导入数据和连接mysql数据库都不需要密码
 连接mysql服务器, 
 mysql> flush privileges; #重新装载授权表
 检查数据是否和备份时一致:
 mysql> use mydb;
 mysql> show tables;
 mysql> desc tb1;
 mysql> select * from tb1;

 8、读取从备份之后产生的二进制日志,获取数据库在上次备份之后执行的操作,重新执行这些操作即可。
 # mysqlbinlog mysql-bin.000004 | mysql -uroot -p


 检查数据是否和故障前一致:
 mysql> use mydb;
 mysql> show tables;
 mysql> desc tb2;
 mysql > select * from tb2;

 重新启用二进制日志记录
 mysql> set global sql_log_bin=1;


二、利用LVM snapshot 备份 mysql 数据库
 lvm snapshot 是个非常好用的功能,它能够对一个 lv 进行“拍照”,此后,可以从快照卷中读取“拍照”那一刻原lv的数据,快照卷的原理在于:最初快照卷并不保存原卷的数据,通

过快照卷访问的其实是原卷上的数据,当原lv的数据发生改变(比如修改、删除)时,LVM 机制会将原卷的需要修改、删除的数据先复制到快照卷,然后才对原卷进行修改。
 如果想要通过备份mysql的数据库文件来进行数据库备份,备份的时候数据时不能写的――否则备份出来的数据就不一致。通过常规途径复制数据库文件由于耗时较久,要求的数据库读

锁定时间比较长,很多时候是不能接受的。如果数据目录是放在lv上,通过对该lv创建快照,之后通过快照来备份原lv里的数据库文件,则只需要“拍照”那一瞬间的锁定而已

 1、刷新表,然后锁定表;记录二进制日志文件当前记录到什么位置(我这次备份之后没有改更新数据库,所以这个没有实际用处,但流程是这样的)
 mysql> FLUSH TABLES WITH READ LOCK; 
 mysql> FLUSH LOGS; 

mysql> SHOW MASTER STATUS; 
+------------------+----------+--------------+------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000007 |      107 |              |                  |
+------------------+----------+--------------+------------------+

 注意千万不要退出mysql终端,在退出mysql终端的时候会隐式的执行unlock tables,在另一终端执行:
 # lvcreate --snapshot --size=100M --name mysnapshot -p r /dev/myvg/lv1 
 赶快回到mysql终端执行
 mysql> UNLOCK TABLES;

 解释:
 FLUSH [log_type] LOGS 
  With no log_type option, FLUSH LOGS closes and reopens all log files. If binary logging is enabled, the sequence number of the binary log file is 

incremented by one relative to the previous file.

 FLUSH TABLES
  :Closes all open tables, forces all tables in use to be closed, and flushes the query cache. FLUSH TABLES also removes all query results from the query 

cache

 FLUSH TABLES WITH READ LOCK
  :Closes all open tables and locks all tables for all databases with a global read lock. This is a very convenient way to get backups if you have a file 

system such as Veritas or ZFS that can take snapshots in time. 


 2、挂载lv 快照,将里面的数据备份出来。
 # mount -t ext4 /dev/myvg/mysnapshot /snap
 # cd /snap/data
 # tar jcvf /bak/mydata.tbz * #进入数据目录进行备份,这样备份的文件就直接在tar归档的根目录下,解档的时候方便
 # umount /snap/

 3、模拟数据库损坏

 4、这次不用重新初始化数据库了,在数据库关闭的状态下,将备份的数据恢复至原数据目录(先将原数据目录里面的内容都删除),修改恢复之后的数据文件的权限,然后重新启动数

据库服务器
 # tar jxvf /bak/mydata.tbz -C /mydata/data
 确保恢复之后的文件权限是正确的,我的不用改文件属主还是mysql
 # /etc/init.d/mysqld start

 数据库启动正常就表明恢复成功,同上,如果在做lv快照之后的数据有更新,应用二进制日志进行更新

三、 利用Xtrabackup进行MySQL备份:

1、简介
Xtrabackup是由percona提供的mysql数据库备份工具,据官方介绍,这也是世界上惟一一款开源的能够对innodb和xtradb数据库进行热备(备份myisam需要锁定表)的工具。特点:
(1)备份过程快速、可靠;
(2)备份过程不会打断正在执行的事务;
(3)能够基于压缩等功能节约磁盘空间和流量;
(4)自动实现备份检验;
(5)还原速度快;
官方网站介绍页面http://www.percona.com/software/percona-xtrabackup
xtrabackup 之所以能够做到物理层面上对数据库文件进行热备,主要是因为它能理解innodb、xtradb的文件格式。
xtrabackup 的执行文件叫innobakupex 。

使用innobakupex备份时,其会调用xtrabackup备份所有的InnoDB表,复制所有关于表结构定义的相关文件(.frm)、以及MyISAM、MERGE、CSV和ARCHIVE表的相关文件,同时还会备份触发器和

数据库配置信息相关的文件。这些文件会被保存至一个以时间命令的目录中。

在备份的同时,innobackupex还会在备份目录中创建如下文件:
(1)xtrabackup_checkpoints ―― 备份类型(如完全或增量)、备份状态(如是否已经为prepared状态)和LSN(日志序列号)范围信息;

每个InnoDB页(通常为16k大小)都会包含一个日志序列号,即LSN。LSN是整个数据库系统的系统版本号,每个页面相关的LSN能够表明此页面最近是如何发生改变的。

(2)xtrabackup_binlog_info ―― mysql服务器当前正在使用的二进制日志文件及至备份这一刻为止二进制日志事件的位置。

(3)xtrabackup_binlog_pos_innodb ―― 二进制日志文件及用于InnoDB或XtraDB表的二进制日志文件的当前position。

(4)xtrabackup_binary ―― 备份中用到的xtrabackup的可执行文件;

(5)backup-my.cnf ―― 备份命令用到的配置选项信息;

在使用innobackupex进行备份时,还可以使用--no-timestamp选项来阻止命令自动创建一个以时间命名的目录;如此一来,innobackupex命令将会创建一个BACKUP-DIR目录来存储备份数据。

2、Xtrabackup的安装很简单,可以下载 percona官方提供的对应发行版的二进制包安装,也可以下载源码安装。
 下载的源码很大,因为里面会包含多个版本的mysql和 percona 版的mysql 源码,源码里面提供有一个 build.sh 脚本,在源码根目录下执行该脚本,并指定对应的mysql版本即可。

详情请读源码里面的说明。
 我的centos 6.4 x86_64 还需要安装 libaio-devel,libgcrypt-devel 和  perl-DBD-MySQL 3个包,其中后两个安装文档里并没有提到


2、备份工作
 a.首先创建一个专门的只有必需的权限的用户给Xtrabackup使用
 mysql> CREATE USER 'bkpuser’@'localhost' IDENTIFIED BY 's3cret';
 mysql> REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'bkpuser'@'localhost';
 mysql> GRANT RELOAD, LOCK TABLES, REPLICATION CLIENT ON *.* TO 'bkpuser'@'localhost';
 mysql> FLUSH PRIVILEGES;

 b.执行完全备份
 # innobackupex --host=localhost --user=bkpuser --password=s3cret  /bak/

3、更新数据库
 mysql> create database db2;
 mysql> use db2;
 mysql> create table singer (id tinyint unsigned auto_increment, name char (30) not null, gender enum ('F','M'),primary key (id));
 mysql> insert into singer (name, gender) values ("cheer chen", 'F'), ('meng tingwei', 'F'), ('cao fang', 'gender');
 mysql> use mydb;
 mysql> drop table distro;
 mysql> create user 'tom'@'localhost' identified by 'tompass';

4、进行xtrabackup进行增量备份
 每个InnoDB的页面都会包含一个LSN信息,每当相关的数据发生改变,相关的页面的LSN就会自动增长。这正是InnoDB表可以进行增量备份的基础,即innobackupex通过备份上次完全

备份之后发生改变的页面来实现。

 # innobackupex --host=localhost --user=bkpuser --password=s3cret --incremental /bak --incremental-basedir=/bak/BACKUP-DIR
 --incremental 指定是增量备份,其参数指定放置增量备份的位置。--incremental-basedir 指定相对于哪次备份的增量备份(可以是之前的完全备份或者增量备份),备份从指定

的上次备份之后改变的数据

5、模拟数据库损坏

6、恢复前的准备工作
 一般情况下,在备份完成后,数据尚且不能用于恢复操作,因为备份的数据中可能会包含尚未提交的事务或已经提交但尚未从事务日志中同步至数据文件中的事务。因此,此时数据

文件仍处理不一致状态。“准备”的主要作用正是通过回滚未提交的事务及同步已经提交的事务至数据文件也使得备份的数据文件处于一致性状态。
 innobakupex命令的--apply-log选项可用于实现上述功能。
 “准备”(prepare)增量备份与整理完全备份有着一些不同,尤其要注意的是:
 (1)需要在每个备份(包括完全和各个增量备份)上,将已经提交的事务进行“重放”。“重放”之后,所有的备份数据将合并到完全备份上。
 (2)基于所有的备份将未提交的事务进行“回滚”。因为一次备份中未提交的事务在之后可能会提交,并被之后的增量备份保存下来。回滚操作也可以在恢复数据后有mysql服务器进行

,因为mysql服务器在启动时发现有未提交事务,会自动进行回滚操作的。

 所以,如果使用了增量备份,在使用--apply-log选项同时要使用--redo-only则表明只重做已提交的事务并写入备份的数据文件,但不回滚未提交的事务。

  这里的准备工作如下:
 # innobackupex --apply-log  --redo-only /bak/BACKUP-DIR
 # innobackupex --apply-log  --redo-only /bak/BACKUP-DIR --incremental-dir=INCREMENTAL-DIR-1
 之后增量备份已经和上次的完整备份合并在一起了。

7、恢复数据
 在数据库关闭的情况下进行数据还原(因为要将整个库的备份写回数据目录,此时数据库当然不能在运行状态中)
 innobackupex命令的--copy-back选项用于执行恢复操作,其通过复制所有数据相关的文件至mysql服务器DATADIR目录中来执行恢复过程。innobackupex通过backup-my.cnf来获取

DATADIR目录的相关信息。

 # innobackupex --copy-back  /bak/BACKUP-DIR
 请确保如上信息的最行一行出现“innobackupex: completed OK!”。

 当数据恢复至DATADIR目录以后,还需要确保所有数据文件的属主和属组均为正确的用户,如mysql,否则,在启动mysqld之前还需要事先修改数据文件的属主和属组。

8、启动 mysql 服务器检验恢复是否成功。

 

 

 

 


 

你可能感兴趣的:(mysql)