三种备份方式
完全备份命令
1,mysqldump实现逻辑角度的热备份、温备
温备
# mysqldump --master-data=2 --all-databases --lock-all-tables > /backup/all.sql
热备
# mysqldump --master-data=2 --single-transaction --all-databases > /backup/all.sql
# cp -r * /backup/
3,xtrabackup实现完全热备份和增量备份
# innobackupex --user=testuser --password=testpwd --host=localhost /backup/
需要注意的地方
1、个人认为mysqldump的温备是最简单的备份方式,就是速度慢了点,适合对少量数据备份。
# mysqldump --master-data=2 --all-databases --lock-all-tables > /backup/all.sql
2、mysqldump备份的时候如果在终端使用了读锁命令,备份完了别忘了解锁
mysql> flush tables with read lock;
mysql> unlock tables;
3、基于逻辑卷的备份,同样如此,在创建快照的时候,肯定会有对表的读锁请求,快照创建完了,就应该立马释放读锁。
4、数据库在被初始化了之后,初始化生成的表会有多种存储引擎,那么,有人就会问,我们备份myisam引擎的表时,需要对表进行加锁,才能备份到完整的数据,那这些自动生成的拥有各种引擎的表,我们复合备份呢。我来给你解惑:
XtraBackup 是一个用来备份 MySQL 的 InnoDB 数据库的开源工具。因此,让它去备份myisam引擎的表,也需要加锁,这样就实现不了热备了。所以,我们在使用mysql时,一定要将默认的存储引擎修改为innodb,最好将这个参数也启用起来掉:innodb_file_per_table=1。而当我们去做备份的时候,其实不用去管那些数据库初始化生成的那些表会不会被完全备份,因为,我们做备份恢复的时候,需要重新初始化的,这些数据都是自动生成的,不需要想太多,只需要在初始化完了之后将存储引擎改为innodb就好说了。
一,mysqldump实现逻辑角度的热备份(施加锁时,也有温备一说)
1,前提
1.1
最好将数据文件单独存放在一个逻辑卷上,然后二进制文件再另外存放在与数据文件不是一个磁盘的地,最好放在非同一个raid上,这样做最保险。
1.2
mysql的安装过程不再演示,详细请看其他博客。
1.3
编辑配置文件,设置数据目录和二进制文件目录
# vim /etc/my.cnf log-bin=/binlog/mysql-bin二进制文件的目录和默认文件名前缀 /binlog二进制文件存放目录,必须修改属组属主为mysql,否则服务启动会报错,/mydata/data 数据目录同样如此。 datadir = /mydata/data数据目录,mydata是逻辑卷的挂载点,data是数据库文件目录 创建备份目录 # mkdir /backup # mkdir /binlog # chown -R mysql.mysql /mydata/data # chown -R mysql.mysql /binlog
假设已经安装完毕,mysql配置完毕,下面说步骤
2,步骤
2.1 初始化mysql,设置数据文件,二进制文件的权限。
# cd /usr/local/mysql # scripts/mysql_install_db --user=mysql --datadir=/mydata/data
/mydata/data是数据目录,/mydata是逻辑卷的挂载点
# ls /binlog
/binlog是二进制文件的存放目录。
2.2初始化完毕,启动服务
# service mysqld start
2.3登录mysql,做一些操作之后,进行完全热备份。
# mysql > create database db;创建数据库 > use db;选择数据库 > create table tb1;创建一张表 > show master status;查看当前二进制文件所在位置,然后进行完全备份 +------------------+----------+--------------+------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | +------------------+----------+--------------+------------------+ | mysql-bin.000001 | 409 | | | +------------------+----------+--------------+------------------+ 1 row in set (0.00 sec)
另起一终端,进行完全备份
# mysqldump --master-data=2 --single-transaction --all-databases > /backup/all.sql
如果有给用户设定权限,不要忘了-u -h -p
--master-data=2 表示将备份时刻所在的二进制文件的位置在备份出的all.sql中注释出来,方便之后查阅。
--single-transaction 通过给数据创建快照,实现了热备份的功能,服务会启动一个超级事务,来处理这种机制
--all-databases 备份所有数据库
--master-data=0 表示不启用此功能
--master-data=1 表示启用,但是以语句的形式显示,我们一般使用2注释出来。
记住此时所在的二进制文件的位置,如上表,mysql-bin.000001 409,做增量备份的时候要用到这个位置。忘记了也没关系,可以使用一下命令查找
# less /backup/all.sql可以看到下面一行
-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=409;
mysqldump还有一种完全备份方式,在备份时给所有的表施加读锁,使数据只读不能写,因此称为温备。
# mysqldump --master-data=2 --lock-all-tables --all-databases --events > /backup/all.sql
2.4系统崩溃前的写操作
当前所在二进制文件是mysql-bin.000001,生产中我们在备份的时候,数据库肯定还有写操作在进行,所以,二进制文件肯定不会就到现在所在的位置,我们要刷新日志,然后对该二进制文件进行增量备份。我们在这里模拟,还有写操作在进行。
> use db; > show tables; > create table tb2(id int); > show master status; +------------------+----------+--------------+------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | +------------------+----------+--------------+------------------+ | mysql-bin.000001 | 494 | | | +------------------+----------+--------------+------------------+
假设,二进制文件在此时结束,我们刷新日志,表示它结束。
>flush logs;
生产中,我们可能做任务计划的时候每天都要让日志刷新,这里就相当与模拟的任务计划中的刷新计划,方便我们对二进制文件的管理。
我们会看到在二进制目录下新增了一个二进制文件mysql-bin.000002
> show master status; +------------------+----------+--------------+------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | +------------------+----------+--------------+------------------+ | mysql-bin.000002 | 107 | | | +------------------+----------+--------------+------------------+
2.5对mysql-bin.000001进行增量备份
# cd /binlog # ls mysql-bin.000001 mysql-bin.index # mysqlbinlog --start-position=409 --stop-position=494 mysql-bin.000001 > /backup/01.sql
别忘了完全备份结束后的二进制文件所在的位置和我们模拟的二进制文件的结束的位置。
注意,增量备份时,如果二进制文件过多,可以先cp二进制文件到备份目录下,然后统一导出,那样速度快一点。
2.6继续对数据库进行修改,然后模拟数据库崩溃
> create table tb3(id int); > show master status; +------------------+----------+--------------+------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | +------------------+----------+--------------+------------------+ | mysql-bin.000002 | 330 | | | +------------------+----------+--------------+------------------+
我们已经在二进制文件mysql-bin.000002 的330上了。
假设,此时数据库崩溃,想一下,我们该如何应对。
2.7首先,我们让服务离线,导出增量备份后,还没有备份的数据。
# service mysqld stop
# mysqlbinlog /binlog/mysql-bin.000002 > /backup/02.sql
2.8模拟数据库崩溃
# rm -rf /mydata/data/*
# rm -rf /binlog/*
2.9重新初始化服务,登录并设置不记录二进制文件
# cd /usr/local/mysql # scripts/mysql_install_db --user=mysql --datadir=/mydata/data # rm -f /binlog/* 初始化的二进制文件没用,删不删都可 # service mysqld start # mysql > set global sql_log_bin=0;
我们要进行备份恢复,因此此时的二进制文件没有,所以,关掉二进制记录程序可以节省空间。注意log_bin 和sql_log_bin 的区别,前者是是否开启二进制日志功能,后者是是否记录二进制文件。开启了前者,后者不开启照样不会记录。
3.0恢复数据
两种方式:登录mysql恢复和非登录恢复。
登录恢复:
> source /backup/all.sql > use db; > show tables; +--------------+ | Tables_in_db | +--------------+ | tb1 | +--------------+
可以看到完全备份时的状态,数据库db中只有一个表
> source /backup/01.sql > show tables; +--------------+ | Tables_in_db | +--------------+ | tb1 | | tb2 | +--------------+
此时两张表
> source < /backup/02.sql > show tables; +--------------+ | Tables_in_db | +--------------+ | tb1 | | tb2 | | tb3 | +--------------+
3.1恢复完毕,开启二进制日志记录功能,并重启服务
> set global sql_log_bin=1; # service mysqld restart
二、基于lvm实现物理层面的几乎热备份
为什么说是几乎完全热备份呢,是因为lvm在在创建快照卷的时候,要确保那一刻的数据是静止的,所有要实现申请所有表的读锁状态。快照创建完了,可以立马释放读锁。之后就是热备份了,而整个过程却并非是完全热备的。
1、准备工作都一样,设置数据目录,二进制文件和备份目录,依然跟上边一样。
数据目录/mydtata/data
二进制文件目录/binlog/
备份目录/backup
数据目录/mydata必须是一个逻辑卷的 挂载点,因为我们要基于lvm实现热备,要对这个目录下的数据创建快照。
2、请求读锁表
> flush tables with read lock;
不要退出,退出后读锁自动释放。
> show master status; +------------------+----------+--------------+------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | +------------------+----------+--------------+------------------+ | mysql-bin.000003 | 107| | | +------------------+----------+--------------+------------------+
查看当前二进制日志所在的位置,这个一定要记住,因为物理备份的数据没有对二进制文件操作,增量备份的数据依赖于这个状态所在的位置。
也可以通过命令
# mysql -ullm -ppass -e 'show master status;' > /tmp/master.sql
将之保存下来
> show engine innodb status\G
注意,请求读锁需要一段时间,不要急着给逻辑卷创建快照,等到缓存中的数据不再变更,再创建快照,否则,数据可能还会有所丢失。
3、另启一终端,对逻辑卷创建快照。
# lvcreate -s -p r -L 100M -n lv2-snap /dev/myvg/lv2 # mkdir /lv2-snap # mount /dev/myvg/lv2-snap /lv2-snap/ # ls /lv2-snap/
Data
4、释放读锁
> unlock tables;
5、基于lvm的物理备份
# cd /mydata/data
# cp -r * /backup/
快慢由数据大小决定。
6、依照第二部读锁表时记录的二进制文件所在位置进行增量备份,直到数据库崩溃。
备份完了就可以恢复了。
7、对数据恢复
第一步就是将备份目录中的文件完全拷贝到数据目录下,别忘了修改数据目录的权限,然后进行增量恢复即可。步骤同mysqldump。
三、基于xtrabackup的热备
安装工具包percona-xtrabackup-2.0.3-470.rhel5.i386.rpm,直接谷歌xtrabackup
安装的时候可能遇到问题,提示依赖包没装,就需要确保perl-Time-HiRes、perl-DBI
和perl-DBD-MySQL已正确安装。
1、一键安装xtrabackup
# rpm -ivh percona-xtrabackup-2.1.4-656.rhel6.x86_64.rpm
2、创建一个具有备份权限的最小权限用户。
mysql> create user 'testuser'@'localhost' identified by 'testpwd'; mysql> revoke all privileges,grant option from 'testuser'@'localhost';
注意,这里的'testuser'@'localhost'必须有’localhost’,否则会报错:
ERROR 1269 (HY000): Can't revoke all privileges for one or more of the requested users mysql> grant reload,lock tables,replication client on *.* to 'testuser'@'localhost'; reload,lock tables,replication client 备份的最小权限。 mysql> flush privileges;
3、对数据库修改,以在恢复的时候做证明。
mysql> create database db1; mysql> use db1; mysql> create table tb1(id int); mysql> show master status; +------------------+----------+--------------+------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | +------------------+----------+--------------+------------------+ | mysql-bin.000004 | 879 | | | +------------------+----------+--------------+------------------+
这个位置在备份目录下的文件/backup/2013-09-08_15-02-36/xtrabackup_binlog_info中有记录
备份完后可以看到
4、以创建好的用户的身份进行完全备份
# innobackupex --user=testuser --password=testpwd --host=localhost /backup/
5、退出登录,停掉服务,模拟数据库崩溃
# service mysqld stop
我经常忘记停止服务,希望你不会跟我一样。
如忘记了停止服务,可以killall mysqld。
# rm -rf /mydata/data/*
注意,二进制日志目录下的文件可别删除,有大用处。
6、恢复前准备
注意,与mysqldump的恢复和基于lvm的恢复不同的是,xtrabackup恢复不需要重新初始化数据库,初始化之后,反而会出问题,而却需要对备份进行准备恢复的处理。
# innobackupex --apply-logpply-log /backup/2013-09-08_15-02-36
--apply-log提交已提交的事务,回滚未回滚的事务
7、直接恢复
# innobackupex --copy-back /backup/2013-09-08_15-02-36
8、登录验证
mysql> use db1; mysql> show tables; +---------------+ | Tables_in_db1 | +---------------+ | tb1 | +---------------+
9、增量备份
接着上边的做,再创建一表
mysql> create table tb2(id int);
增量备份
# innobackupex --incremental /backup --incremental-basedir=/backup/2013-09-08_15-34-30
10、恢复前准备
# innobackupex --apply-log --redo-only /backup/2013-09-08_15-34-30 先对完全备份做准备 --apply-log 提交已提交的,撤销未提交的 --redo-only 对数据重放,“重放”之后,所有的备份数据将合并到完全备份上。 # innobackupex --apply-log --redo-only /backup/2013-09-08_15-34-30 --incremental-dir=/backup/2013-09-08_15-47-29
对增量备份做准备
11、退出服务,关闭服务,模拟崩溃
# service mysqld stop # rm -rf /mydata/data/*
12、做备份恢复
# innobackupex --copy-back /backup/2013-09-08_15-34-30
13、启动前别忘了修改数据目录下文件的权限,否则无法启动服务
# chown -R mysql.mysql /mydata/data/* # service mysqld start
14、登录查看恢复是否成功
mysql> show tables; +---------------+ | Tables_in_db1 | +---------------+ | tb1 | | tb2 | +---------------+
发现我们增量备份的第二张表也回来了。
Xtrabackup小结:
与mysqldump和基于lvm的备份相同,当数据真正出现问题的时候,我们备份的只是当前一段时间之前的数据,比如我们备份的是昨天的数据。而要将数据恢复到今天中午之前,就不能再使用这种方式进行备份了,通过样需要使用二进制文件进行备份,即使用mysqlbinlog导出二进制文件,后续工作不再总结,都在mysqldump中做了总结,不会请看上边
mysqldump2.5中的内容。
同时罗嗦一句,二进制文件重要非常,一定要妥善管理,不要一失足成千古恨。