基于Innobackupex的不完全恢复
2014年12月26日 14:15:57
阅读数:3259
对于MySQL的不完全恢复,我们可以借助于Innobackupex的多重备份加上binlog来将数据库恢复到任意时刻。这里的不完全恢复(也叫时点恢复)是相对于完全恢复。本文主要演示了基于Innobackupex如何做一个不完全恢复,供大家参考。
有关Innobackupex的备份恢复的知识点请参考以下链接:
1、不完全恢复的概念
不完全恢复,即时点恢复,是指使用备份加上binlog日志将数据库恢复到任意指定的时间点。
不完全恢复依赖于完整的数据库备份与binlog备份,只要2者存在,任意数据丢失,误操作,都可以恢复到任意指定的时间点。
不完全恢复的概念不限于热备与逻辑备份(mysqldump)方式,都可以实现不完全恢复。
2、演示备份过程
[sql] view plain copy
print?
- a、创建演示环境
- robin@localhost[(none)]> show variables like 'version'; --当前MySQL版本
- +---------------+------------+
- | Variable_name | Value |
- +---------------+------------+
- | version | 5.6.12-log |
- +---------------+------------+
- robin@localhost[(none)]> reset master;
- Query OK, 0 rows affected (0.03 sec)
- robin@localhost[(none)]> use tempdb;
- robin@localhost[tempdb]> create table tb(id smallint,val varchar(20));
- robin@localhost[tempdb]> insert into tb values(1,'fullbak');
- --创建一个全备
- SHELL> innobackupex --user=robin -password=xxx --port=3606 --socket=/tmp/mysql3606.sock --defaults-file=/etc/my3606.cnf \
- > /hotbak/full --no-timestamp
- b、创建一个增备
- --在创建增备前插入一条记录到tb
- robin@localhost[tempdb]> insert into tb values(2,'Incbak');
- SHELL> innobackupex --user=robin -password=xxx --port=3606 --socket=/tmp/mysql3606.sock --defaults-file=/etc/my3606.cnf \
- > --incremental /hotbak/inc --incremental-basedir=/hotbak/full --no-timestamp
- --再次新增一条记录
- robin@localhost[tempdb]> insert into tb values(3,'pointrecover');
- Query OK, 1 row affected (0.01 sec)
- --记下当前的时间点用于后续的不完全恢复
- robin@localhost[tempdb]> system date;
- Thu Dec 25 11:53:54 CST 2014
- --模拟误操作
- robin@localhost[tempdb]> truncate table tb;
- Query OK, 0 rows affected (0.01 sec)
- c、再次全备
- SHELL> innobackupex --user=robin -password=xxx --port=3606 --socket=/tmp/mysql3606.sock --defaults-file=/etc/my3606.cnf \
- > /hotbak/full2 --no-timestamp
- --全备后新增一张表
- robin@localhost[tempdb]> create table tb_after_truncate(id int,val varchar(20));
- Query OK, 0 rows affected (0.02 sec)
3、演示恢复过程
[sql] view plain copy
print?
- --下面理清一下思路:
- --当前备份情况: 全备+增备+全备
- --我们在增备之后truncate了表tb,然后又创建了一个全备,新建了一个表tb_after_truncate。
- --此时我们需要将数据库恢复到truncate(误操作)之前
- --解决方案:我们需要利用第一次的全备+增备+binglog来恢复到truncate前,当前第二次全备用不上。
- a、先做基于全备的apply,注意,此时使用了--redo-only
- SHELL> innobackupex --apply-log --redo-only --user=robin -password=xxx --port=3606 \
- > --defaults-file=/etc/my3606.cnf /hotbak/full
- b、基于增备的apply,
- --此时没有--redo-only,如果有多个增备,仅仅最后一个增备无需指定--redo-only
- SHELL> innobackupex --apply-log --user=robin -password=xxx --port=3606 --defaults-file=/etc/my3606.cnf \
- > /hotbak/full --incremental-dir=/hotbak/inc
- c、进行copy back
- SHELL> mysqldown -P3606 --copy back前关闭实例
- SHELL> netstat -nltp|grep mysql|grep 3606
- SHELL> mv /data/inst3606/data3606 /data/inst3606/data3606bk
- SHELL> mkdir -p /data/inst3606/data3606
- SHELL> innobackupex --user=robin -password=xxx --port=3606 --copy-back /hotbak/full --defaults-file=/etc/my3606.cnf
- SHELL> chown -R mysql:mysql /data/inst3606/data3606
- d、启动恢复后的实例
- SHELL> mysqld_safe --defaults-file=/etc/my3606.cnf &
- SHELL> mysql -uroot -pxxx -P3606 -S /tmp/mysql3606.sock \
- > -e "select * from tempdb.tb"
- Warning: Using a password on the command line interface can be insecure.
- +------+---------+
- | id | val |
- +------+---------+
- | 1 | fullbak |
- | 2 | Incbak |
- +------+---------+
- --获取增量之后的log position
- SHELL> cd /hotbak/inc/
- SHELL> more xtrabackup_binlog_info
- inst3606bin.000001 774
- --这里使用了stop-datetime去将日志追加到truncate之前
- SHELL> mysqlbinlog /data/inst3606/log/bin/inst3606bin.000001 --start-position=774 --stop-datetime="2014-12-25 11:53:54" \
- > |mysql -urobin -pxxx -P3606 -S /tmp/mysql3606.sock
- --验证结果如下,可以看到已经恢复到truncate之前了
- SHELL> mysql -uroot -pxxx -P3606 -S /tmp/mysql3606.sock \
- > -e "select * from tempdb.tb"
- Warning: Using a password on the command line interface can be insecure.
- +------+--------------+
- | id | val |
- +------+--------------+
- | 1 | fullbak |
- | 2 | Incbak |
- | 3 | pointrecover |
- +------+--------------+
- --如果我们需要继续恢复后面的事务,我们可以找出truncate前后位置,然后跳过这个position
- SHELL> mysqlbinlog /data/inst3606/log/bin/inst3606bin.000001 --start-datetime="2014-12-25 11:53:54"|grep truncate -A5
- truncate table tb
- /*!*/;
- # at 1180
- #141225 11:55:35 server id 3606 end_log_pos 1260 CRC32 0x12f55fc5 Query thread_id=928 exec_time=0 error_code=0
- SET TIMESTAMP=1419479735/*!*/;
- /*!\C latin1 *//*!*/;
- --
- create table tb_after_truncate(id int,val varchar(20))
- /*!*/;
- # at 1392
- #141225 13:06:47 server id 3606 end_log_pos 1415 CRC32 0xf956f311 Stop
- DELIMITER ;
- # End of log file
- --我们找出的position为1260,跳过1260之前的继续追加binlog
- SHELL> mysqlbinlog /data/inst3606/log/bin/inst3606bin.000001 --start-position=1260 \
- > |mysql -urobin -pxxx -P3606 -S /tmp/mysql3606.sock
- --验证追加后的结果,可以看到表tb_after_truncate存在
- [mysql@app ~]$ mysql -uroot -pxxx -P3606 -S /tmp/mysql3606.sock \
- > -e "desc tempdb.tb_after_truncate"
- Warning: Using a password on the command line interface can be insecure.
- +-------+-------------+------+-----+---------+-------+
- | Field | Type | Null | Key | Default | Extra |
- +-------+-------------+------+-----+---------+-------+
- | id | int(11) | YES | | NULL | |
- | val | varchar(20) | YES | | NULL | |
- +-------+-------------+------+-----+---------+-------+
4、小结
a、不完全恢复(时点恢复)与完全恢复操作方式上基本等同
b、不完全恢复我们需要确定需要恢复到的时间点或binlog position
c、一旦确定了需要恢复的时间点,选择自上一次全备以来所有备份来进行恢复
d、恢复完成后再使用binlog日志追加到确定的时间点
e、追加binlog日志可以基于position,也可以基于datetime
f、也可以跳过故障点,继续追加后面的binlog日志至最新,如本文尾部的演示