一个简单的binlog恢复测试

日常的数据备份及恢复测试,是DBA工作重中之重的事情,所以要做好备份及测试,日常的备份常见有mysqldump+binlog备份、xtrabackup+binlog备份,无论那一种,几乎都少不了对binlog的备份,说明了binlog在数据恢复中的重要性,下面做个小测试,是工作中不少运维或者新人DBA容易犯的错。

创建一个测试表tb1:

<test>([email protected]) [xuanzhi]> show create table tb1\G
*************************** 1. row ***************************
       Table: tb1
Create Table: CREATE TABLE `tb1` (
  `id` int(10) NOT NULL AUTO_INCREMENT,
  `name` char(10) CHARACTER SET latin1 DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

<test>([email protected]) [xuanzhi]> 

往表里插入两条数据:

<test>(root@localhost) [xuanzhi]> insert into tb1 (name)  value (‘aa‘),(‘bb‘);
Query OK, 2 rows affected (0.01 sec)
Records: 2  Duplicates: 0  Warnings: 0

<test>(root@localhost) [xuanzhi]> show master logs;
+----------------------+-----------+
| Log_name             | File_size |
+----------------------+-----------+
| localhost-bin.000001 |       329 |
+----------------------+-----------+
1 row in set (0.00 sec)

<test>(root@localhost) [xuanzhi]> 

这个时候对数据备份,如果是xtrabackup备份的话,会在有xtrabackup_binlog_info文件中记录此时备份是到那个binlog文件和pos点的,如果是mysqldump备份,则需要带上--master-data=2这个参数,下面我们的数据量少,用mysqldump备份:

[[email protected] ~]# mysqldump -uroot -p123456  -R --events --triggers=true --master-data=2 --single-transaction xuanzhi > xuanzhi.sql
Warning: Using a password on the command line interface can be insecure.
[[email protected] ~]# grep -i "CHANGE MASTER" xuanzhi.sql
-- CHANGE MASTER TO MASTER_LOG_FILE=‘localhost-bin.000001‘, MASTER_LOG_POS=329;
[[email protected] ~]# 

备份完后,继续模拟数据库有写入,而还是写在localhost-bin.000001

<test>(root@localhost) [xuanzhi]> insert into tb1 (name)  value (‘cc‘),(‘dd‘);
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0

<test>(root@localhost) [xuanzhi]> show master logs;
+----------------------+-----------+
| Log_name             | File_size |
+----------------------+-----------+
| localhost-bin.000001 |       538 |
+----------------------+-----------+
1 row in set (0.00 sec)

<test>(root@localhost) [xuanzhi]> flush logs;
Query OK, 0 rows affected (0.01 sec)

<test>(root@localhost) [xuanzhi]> insert into tb1 (name)  value (‘ee‘);
Query OK, 1 row affected (0.00 sec)

<test>(root@localhost) [xuanzhi]> show master logs;
+----------------------+-----------+
| Log_name             | File_size |
+----------------------+-----------+
| localhost-bin.000001 |       589 |
| localhost-bin.000002 |       321 |
+----------------------+-----------+
2 rows in set (0.00 sec)

<test>(root@localhost) [xuanzhi]> 

上面我们进行flush logs是为了模拟现在已经有多个binlog文件了,恢复时进行多个binlog一起恢复。

进行误操,把xunazhi库drop了:

<test>(root@localhost) [xuanzhi]> drop database xuanzhi;
Query OK, 1 row affected (0.02 sec)

<test>(root@localhost) [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| test               |
+--------------------+
4 rows in set (0.00 sec)

<test>(root@localhost) [(none)]> 

创建数据xuanzhi,把备份导入:

<test>(root@localhost) [(none)]> create database xuanzhi;
Query OK, 1 row affected (0.00 sec)
[[email protected] ~]# mysql -uroot -p123456 xuanzhi <./xuanzhi.sql
Warning: Using a password on the command line interface can be insecure.
[[email protected] ~]# 

查看数据:

<test>(root@localhost) [(none)]> use xuanzhi
Database changed
<test>(root@localhost) [xuanzhi]> select * from tb1;
+----+------+
| id | name |
+----+------+
|  1 | aa   |
|  2 | bb   |
+----+------+
2 rows in set (0.00 sec)

<test>(root@localhost) [xuanzhi]> 

可以看到备份前的数据恢复了,我们现在要结合Binlog来恢复,但前提要找出误操作前的pos点,也就是drop database xuanzhi前的pos点:

[[email protected] ~]# mysqlbinlog -v --base64-output=DECODE-ROWS localhost-bin.000002 |grep -C 10  -i "drop database"
### INSERT INTO `xuanzhi`.`tb1`
### SET
###   @1=5
###   @2=‘ee‘
# at 290
#170327 21:10:55 server id 1313306  end_log_pos 321 CRC32 0x825a2f99    Xid = 78
COMMIT/*!*/;
# at 321
#170327 21:19:25 server id 1313306  end_log_pos 422 CRC32 0x8c139cac    Query   thread_id=2     exec_time=0     error_code=0
SET TIMESTAMP=1490620765/*!*/;
drop database xuanzhi
/*!*/;
DELIMITER ;
# End of log file
ROLLBACK /* added by mysqlbinlog */;
/*!50003 SET [email protected]_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;
[[email protected] ~]# mysql -uroot -p123456 xuanzhi <./xuanzhi.sql
Warning: Using a password on the command line interface can be insecure.
[[email protected] ~]# 

从上面可以看到,误操作前的pos点是321,那我们现在通过binlog来进行数据恢复:

[[email protected] mysql-5.6]# mysqlbinlog --start-position=329 --stop-position=321 localhost-bin.000001 localhost-bin.000002 |mysql -uroot -p123456 xuanzhi
Warning: Using a password on the command line interface can be insecure.
[[email protected] mysql-5.6]# 

--start-position是备份后记录下的pos点, --stop-position是误操前的pos点,如果批多个binlog文件,那么start-position是第一个binlog文件的pos点,stop-position是最后一个binlog的pos点,下面我们看下数据是否恢复回来了:

<test>(root@localhost) [xuanzhi]> select * from tb1;
+----+------+
| id | name |
+----+------+
|  1 | aa   |
|  2 | bb   |
|  3 | cc   |
|  4 | dd   |
|  5 | ee   |
+----+------+
5 rows in set (0.00 sec)

<test>(root@localhost) [xuanzhi]> 

这里要提的是进行恢复前,要把需要恢复的binlog备份好,或者移动拷贝一份到另一个目录,因为进行数据导入时也会继续写binlog。假如你没有误操作的情况下,就是想测试一下数据的恢复,很多人的操作是导入备份,再从备份里记录的binlog文件名和pos点进行binlog恢复,发现步骤都很完美,也没报错,就是只有备份的数据,没有备份后的数据,下面测试一下给大家看:

<test>(root@localhost) [xuanzhi]> insert into tb1 (name)  value (‘aa‘),(‘bb‘);
Query OK, 2 rows affected (0.01 sec)
Records: 2  Duplicates: 0  Warnings: 0

<test>(root@localhost) [xuanzhi]> select * from tb1;
+----+------+
| id | name |
+----+------+
|  1 | aa   |
|  2 | bb   |
+----+------+
2 rows in set (0.00 sec)
<test>(root@localhost) [xuanzhi]> show master logs;
+----------------------+-----------+
| Log_name             | File_size |
+----------------------+-----------+
| localhost-bin.000001 |       329 |
+----------------------+-----------+
1 row in set (0.00 sec)

<test>(root@localhost) [xuanzhi]> 

进行备份操作:

[[email protected] ~]# mysqldump -uroot -p123456 -R --events --triggers=true --master-data=2 --single-transaction xuanzhi > xuanzhi.sql
Warning: Using a password on the command line interface can be insecure.
[[email protected] ~]# grep -i "change master" xuanzhi.sql
-- CHANGE MASTER TO MASTER_LOG_FILE=‘localhost-bin.000001‘, MASTER_LOG_POS=329;
[[email protected] ~]# 

继续写localhost-bin.000001后进行flush logs生成新的binlog再继续写数据,这里只是想模拟localhost-bin.000001写满了切localhost-bin.000002,结合多个binlog一起恢复

<test>([email protected]) [xuanzhi]> insert into tb1 (name)  value (‘cc‘),(‘dd‘);
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0

<test>([email protected]) [xuanzhi]> flush logs;
Query OK, 0 rows affected (0.00 sec)

<test>([email protected]) [xuanzhi]> insert into tb1 (name)  value (‘dd‘);
Query OK, 1 row affected (0.01 sec)

<test>([email protected]) [xuanzhi]> show master logs;
+----------------------+-----------+
| Log_name             | File_size |
+----------------------+-----------+
| localhost-bin.000001 |       589 |
| localhost-bin.000002 |       321 |
+----------------------+-----------+
2 rows in set (0.00 sec)

<test>([email protected]) [xuanzhi]> 

下面进行恢复测试,正常来说先把备份导入:

[[email protected] ~]# mysql -uroot -p123456 xuanzhi <./xuanzhi.sql
Warning: Using a password on the command line interface can be insecure.
[[email protected] ~]# 

查看数据,只有备份的那两条记录:

<test>([email protected]) [xuanzhi]> select * from tb1;
+----+------+
| id | name |
+----+------+
|  1 | aa   |
|  2 | bb   |
+----+------+
2 rows in set (0.00 sec)

<test>([email protected]) [xuanzhi]> 

那现在通过localhost-bin.000001,localhost-bin.000002来恢复后面那3条数据,那么起始pos是那个呢,就是上面备份完后备份文件里的那个pos,我们进到binlog的存放路径:

可以看到备份后的数据是没有恢复回来的。为什么呢?因为导入备份的时候,又开始写binlog了,而你恢复时用的binlog也就是现在导入备份时正在写的binlog。大体过程是这样的:

1、导入备份后,备份的所有操作都写进最后一个binlog了,也就是上面的localhost-bin.000002

2、进行binlog恢复,从备份文件里的pos点开始,按理来说是可以恢复到最新数据的,但是上面导入了备份,导入时的所有操作都会记录到localhost-bin.000002

3、备份导入时会有DROP TABLE和CREATE TABLE的动作写进binlog里,所以最终得到的数据,还是备份时的数据。

总结:

        一、在恢复全备数据之前必须将该binlog文件移出,否则恢复过程中,会继续写入语句到binlog,最终导致增量恢复数据部分变得比较混乱

        二、做好数据文件及binlog的备份至关重要,但不是备份完就算了,要定期进行数据恢复测试或演练

        三、恢复时建议对外停止更新,即禁止更新数据库


作者:陆炫志

出处:xuanzhi的博客 http://www.cnblogs.com/xuanzhi201111

您的支持是对博主最大的鼓励,感谢您的认真阅读。本文版权归作者所有,欢迎转载,但请保留该声明。

时间: 2024-10-19 02:17:25

一个简单的binlog恢复测试的相关文章

一个简单的函数指针测试例子

一般函数指针的一个简单测试.将函数放到vector里面,将函数作为形参. 1 typedef void(*GTestFunPtr)(int, int); 2 3 void test1(int a, int b) 4 { 5 std::cout << "test1:" << a + b << std::endl; 6 } 7 8 void test2(int a, int b) 9 { 10 std::cout << "test2

一个简单的通用协议测试软件

在一个公司看到的一个协议测试系统,用C#实现,然后在里面可以按照自己的想法完全自定义字段属性什么的. 之前老是调试服务器与客户端,每次都为了协议的事调试半天,两边都要配人,很影响效率,最近加入一家公司又听闻此事重演,有心想做这样的一个测试软件,这个软件只是用来调试协议,提供测试数据,并显示返回的测试数据. 考虑到PC上写程序好像确实C#容易些,不过协议解析之前用python搞过,有意向将之结合,C#做一些界面,python完成自定义协议实现,初步实现tcp,http两种,协议字段初步考虑用xml

[软件测试学习]考虑到测试的代码编写/int.parse的非法输入—由一个简单的c#闰年检测程序说起

一个简单的C#的闰年检测程序 1.闰年检测的函数编写 当提起检测平年闰年时候,第一反应写出的代码 1 public static bool isLeapYear(int year){ 2 return ((year % 4 == 0 && year % 100 != 0)||(year % 400 == 0)) 3 } 但是这个并不易于测试和出现错后的修改,更改代码如下 1 public static bool isLeapYear(int year){ 2 bool check = ne

一个简单的HTTP测试工具:Send HTTP Tool

我们在调用或者测试测试HTTP协议,或者第三方系统公布的RESTFul Web服务的API的时候,可以有很多种方法,比如,自己在cmd行中,打开telnet,然后拼写HTTP的数据:或者用Fiddler2发送HTTP请求的数据:还有其他方式:直接用telnet命令,拼写HTTP的数据很不方便,而且很容易出错:Fiddler2虽然功能强大,但是个人感觉使用起来有点稍微复杂,特别是对初学者来说.那么有没有一个简单,易于使用,一看就能知道如何使用的发送HTTP请求数据的工具呢?在这个篇文章中,为给大家

jmeter压力测试的简单实例+badboy脚本录制(一个简单的网页用户登录测试的结果)

JMeter的安装:在网上下载,在下载后的zip解压后,在bin目录下找到JMeter.bat文件,双击就可以运行JMeter. http://jmeter.apache.org/ 在使用jmeter前要先下载jdk包,配置java环境.(参见Java环境配置教程) 配置完成后在运行窗口检查一下java -version确定java环境配置完成. 一.利用badboy进行自动脚本录制 下载BadboyInstaller-2.2.5.exe 并安装 下载地址:http://download.csd

xtrabackup 备份mysql数据库三: innobackupex 测试一个全量和两个增量的备份恢复测试

## 查看当前库中表的数据 ([email protected]) [test]>select count(*) from t_innodb; +----------+ | count(*) | +----------+ |        0 | +----------+ 1 row in set (0.00 sec) ## 执行插入数据操作,该操作在全备之后执行完成 ([email protected]) [test]>call addTest(100000,0); ## 执行全库备份 #

测试工具之Jmeter(创建一个简单测试用例)

前面介绍了如何使用badboy录制jmeter脚本,以及如何导入脚本并进行测试 这里介绍下手动创建测试用例,主要步骤如下: 1.创建线程组 第一次打开Jmeter只有一个测试计划,右键"测试计划"选择"添加" -> "Threads" -> "线程组",即可得到如下配置界面: 名称:即这个线程组的名字 注释:对这个线程组的注释 在取样器执行错误后的操作:根据需要勾选后续执行情况,一般都会选择继续 线程数:即总的测试

【SpingBoot】 测试如何使用SpringBoot搭建一个简单后台1

很久没写博客了,最近接到一个组内的测试开发任务是做一个使用SpringBoot 开发一个后台程序(还未完成),特写感想记录一下 1. 为什么选择SpringBoot ? 首先是目前很多公司的后台还是JAVA编写的,或者直接就是MVC的一个后台,大部分测试其实会采用python 作为一个测试语言,易上手然后见效快. 但是我们可以想见,其实在传统行业,领导更希望你能够使用同一种语言来进行一些程序或者代码的编写. PS: 其实是因为我自己报的,我说了python或者springboot都可以,领导给我

一个简单的记事本编辑框的实现以及搜集的一些窗口风格的预定义

这是一个简单的记事本的窗口过程 1 WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM 2 3 LOCAL winRect:RECT 4 LOCAL editWidth:DWORD 5 LOCAL editHeight:DWORD 6 7 .IF uMsg==WM_DESTROY 8 invoke PostQuitMessage,NULL 9 .ELSEIF uMsg==WM_CREATE 10 ;创建一个编辑框 11