由于运维、DBA的误操作或是业务bug,我们在操作中时不时会出现误删除数据情况。早期要想恢复数据,只能让业务人员根据线上操作日志,构造误删除的数据,或者DBA使用binlog和备份的方式恢复数据,不管那种,都非常费时费力,而且容易出错。直到彭立勋首次在MySQL社区为mysqlbinlog扩展了闪回功能。

在美团点评,我们也遇到过研发人员误删主站的配置信息,从而导致主站长达2个小时不可用的情况。DBA同学当时使用了技术团队自研的binlog2sql完成了数据恢复,并多次挽救了线上误删数据导致的严重故障。不过,binlog2sql在恢复速度上不尽如人意,因此我们开发了一个新的工具——MyFlash,它很好地解决了上述痛点,能够方便并且高效地进行数据恢复。

先来看下目前市面上已有的恢复工具,我们从实现角度把它们划分成如下几类。

① mysqlbinlog工具配合sed、awk。该方式先将binlog解析成类SQL的文本,然后使用sed、awk把类SQL文本转换成真正的SQL。

* 优点:当SQL中字段类型比较简单时,可以快速生成需要的SQL,且编程门槛也比较低。

* 缺点:当SQL中字段类型比较复杂时,尤其是字段中的文本包含HTML代码,用awk、sed等工具时,就需要考虑极其复杂的转义等情况,出错概率很大。

② 给数据库源码打patch。该方式扩展了mysqlbinlog的功能,增加Flashback选项。

* 优点:复用了MySQL Server层中binlog解析等代码,一旦稳定之后,无须关心复杂的字段类型,且效率较高。

* 缺点:在修改前,需要对MySQL的复制代码结构和细节需要较深的了解。版本比较敏感,在MySQL 5.6上做的patch,基本不能用于MySQL 5.7的回滚操作。升级困难,因为patch的代码是分布在MySQL的各个文件和函数中,一旦MySQL代码改变,特别是复制层的重构,升级的难度不亚于完全重新写一个。

③ 使用业界提供的解析binlog的库,然后进行SQL构造,其优秀代表是binlog2sql。

* 优点:使用业界成熟的库,因此稳定性较好,且上手难度较低。

* 缺点:效率往往较低,且实现上受制于binlog库提供的功能。

上述几种实现方式,主要是提供的过滤选项较少,比如不能提供基于SQL类型的过滤,需要回滚一个delete语句,导致在回滚时,需要结合awk、sed等工具进行筛选。

总结了上述几种工具的优缺点,我认为理想的闪回工具需要有以下特性。

a. 无需把binlog解析成文本,再进行转换。

b. 提供原生的基于库、表、SQL类型、位置、时间等多种过滤方式。

c. 支持MySQL多个版本。

d. 对于数据库的代码重构不敏感,利于升级。

e. 自主掌控binlog解析,提供尽可能灵活的方式。

在这些特性中,binlog的解析是一切工作的基础。接下来我会介绍binlog的基本结构。

binlog格式概览

一个完整的binlog文件是由一个format description event开头,一个rotate event结尾,中间由多个其他event组合而成。

binlog文件实例:

每个event都是由event header 和event data组成。下面简单介绍下几种常见的binlog event。

① formart description event

表达的含义是:170905 01:59:33 server id 10 end_log_pos 123 CRC32 0xed1ec563

Start: binlog v 4, server v 5.7.18-log created 170905 01:59:33

② table map event

表达的含义是:170905 01:59:33 server id 10 end_log_pos 339 CRC32 0x3de40c0d

Table_map: `test`.`test4` mapped to number 238

③ update row event

表达的含义是:170905 01:59:33 server id 10 end_log_pos 385 CRC32 0x179ef6dd

Update_rows: table id 238 flags: STMT_END_F

UPDATE `test`.`test4` WHERE @1=3 SET @1=13;

binlog event回滚

根据上面的binlog介绍,可以看到每个binlog event中event header有个type_code,其中insert为30,update为31,delete为32。对于insert和delete两个相反的操作,只需把type_code互换,则在binlog event级别完成回滚。

而对于update操作,其格式如下。

其中,BI是指before image,AI是指after image。

我们只需依次遍历修改前的数据和修改后的数据,并一一互换即可。因此整个回滚操作的难点在于回滚update语句,而update语句回滚的核心在于计算出每个AI、BI的长度。下面介绍下长度以及部分字段的计算方法。

镜像长度计算

镜像是由一个个字段组成的,根据字段类型的不同,其计算长度的方法也不一样。只与字段类型相关。比如int占用4个字节,bingint占用8个字节。其中类型信息可以从table map event中获取。

与字段类型及其参数相关。比如decimal(18,9),占用9个字节,参数信息在table map event中。

与字段类型、参数以及实际存储的值相关。比如varchar(10),有1个字节表示长度,之后的字节才表示真正的数据。比如varchar(280),有2个字节表示长度。实际的长度和数据在一起。

解析binlog中的若干个关键点

① length encoded integer

binlog中一个或者多个字节组合,分别表示了不同的含义。比如,timestamp是由固定的4个字节组成,event类型由一个字节表示;数据库名和表名最长为64个字符,即使每个字符占用3个字节,那么占用的字节数为192<255。因此最多使用一个字节,就可以完成实际长度表示。

然而列的实际数量,可能需要超过1个字节、2个字节、3个字节甚至8个字节去表示。如果我们使用最大的8个字节去表示,那么在绝大多数情况下都是浪费存储空间的。针对这种情况,length encoded integer应运而生。

比如在获取一个varchar类型的长度时,首先读取第一个字节,如果值小于251,那么varchar的长度就是第一个字节表示的长度。如果第一个字节的值为0xFC,那么varchar的长度是由该字节之后的后两个字节组成,以此类推。

② decimal类型

decimal是由整数部分和小数部分组成。无论是整数还是小数,每9个数字,需要4个字节。如果不是9的倍数,剩余的小数位,需要的字节数如下,为方便描述,将该关系定义为函数Fnum。

举例,对于 decimal(18,10):整数部分可展示的为8,用int,即4个字节。

小数部分,需要的字节数为 (10 /9)*4+Fnum(10%9)=5。

那么总共加起来需要4+5=9个字节。

在上面的章节中,介绍了单个binlog event的反转方法。在实践中,我们往往需要把某个binlog,按照指定的条件,过滤出需要的binlog,并进行反转。那么MyFlash是如何完成这些目标的呢?

解析binlog

首先把binlog文件,解析成多个event,放入到相关队列中。在实现上,为了尽可能加快解析速度,可以让用户指定解析的开始与结束位置。把binlog文件解析成binlog event后,再判断下是否符合指定的时间条件,若不符合,则丢弃该event。

注意:用户可以不指定位置和时间,则解析整个文件。如果只指定时间,那么也需要从文件开始处解析,取出时间信息,再进行判断。因此,当需要回滚的binlog只占整个binlog的一小部分时,推荐使用指定位置。

重组event

把binlog event组成最小执行单元。在常见的binlog event中table_map event包含了所要了表名、库名等元数据信息,而row_event(包含write_event、delete_event、update_event)包含了真正的数据。因此在设计中使用了一个最小执行单元概念。所谓的最小执行单元,即least execution event unit,通常包含一个table_map event和若干个row_event。

比如在binlog格式概览一节中,介绍了table_map_event和update_row_event。如果只有update_row_event,那么我们无法知道这个event对应的行记录变更对应的表。因此一个完整的最小执行单元最少包含一个table_map_event和write_row_event、update_row_even、delete_row_event中的一个。

为什么我们需要使用最小执行单元?因为我们在闪回操作时,不能简单的把每个event反转之后,然后再将所有event的顺序反转过来。如果这样的话,就会出现table_map event在row event之后,这显然是违反binlog执行逻辑的。

有了最小执行单元之后,只需两步,即可完成反转。

a. 反转最小执行单元中的row event。

b. 逆序最小执行单元队列,即可。

当然在反转前,也可以增加过滤操作。比如过滤库名、表名和SQL类型等。

生成binlog文件

有了逆序的最小执行单元队列后,只需把每个最小执行单元依次输入到文件即可。不过不要忘了修改每个binlog event里的next_position,用来表示下一个binlog的位置。

测试场景

使用testFlashback2,插入100万条数据:CREATE TABLE `testFlashback2` (

`id` int(11) NOT NULL AUTO_INCREMENT,

`nameShort` varchar(20) DEFAULT NULL,

`nameLong` varchar(260) DEFAULT NULL,

`amount` decimal(19,9) DEFAULT NULL,

`amountFloat` float DEFAULT NULL,

`amountDouble` double DEFAULT NULL,

`createDatetime6` datetime(6) DEFAULT NULL,

`createDatetime` datetime DEFAULT NULL,

`createTimestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,

`nameText` text,

`nameBlob` blob,

`nameMedium` mediumtext,

PRIMARY KEY (`id`)

) ENGINE=InnoDB

mysql> select count(*) from testFlashback2;

+----------+

| count(*) |

+----------+

| 1048576 |

+----------+

1 row in set (0.16 sec)

delete from testFlashback2;

测试结果

从上述图表中可以看出,MyFlash的速度最快。

美团mysql 闪回_MyFlash——美团点评的开源MySQL闪回工具相关推荐

  1. MyFlash——美团点评的开源MySQL闪回工具

    由于运维.DBA的误操作或是业务bug,我们在操作中时不时会出现误删除数据情况.早期要想恢复数据,只能让业务人员根据线上操作日志,构造误删除的数据,或者DBA使用binlog和备份的方式恢复数据,不管 ...

  2. 利用MySQL实现一个类似美团外卖的外卖订单的数据库管理系统

    利用MySQL实现一个类似美团外卖的外卖订单的数据库管理系统 本文的重点在于MySQL触发器的应用 1.数据库需求分析 ​ 1)数据库实体:客户.商家.商品.订单. ​ 2)一个客户对应多个订单. ​ ...

  3. 【AI in 美团】深度学习在美团搜索广告排序的应用实践

    转自:https://mp.weixin.qq.com/s/9Fcj5lO-JPfFVnRSSM_56w [AI in 美团]深度学习在美团搜索广告排序的应用实践 AI(人工智能)技术已经广泛应用于美 ...

  4. mysql 回滚_一个集审核、执行、备份及生成回滚语句于一身的MySQL运维工具

    goInception 一个集审核.执行.备份及生成回滚语句于一身的MySQL运维工具, 通过对执行SQL的语法解析,返回基于自定义规则的审核结果,并提供执行和备份及生成回滚语句的功能 架构图 使用方 ...

  5. mysql找不到sys_解决方法:①MySQL 闪退 ②服务列表里找不到MySQL ③MySQL服务无法启动...

    昨天下了WampServer差点没把我气死,下下来之后也不好使,还显示丢失啥啥啥文件,(´°̥̥̥̥̥̥̥̥ω°̥̥̥̥̥̥̥̥`) 然后MySQL也不好使.心态崩了.下面说一下MySQL遇到的问题以 ...

  6. 美团小哥用计算机,美团2020算法工程师编程题--外卖小哥的保温箱

    题目描述: 众所周知,美团外卖的口号是:"美团外卖,送啥都快".身着黄色工作服的骑手作为外卖业务中商家和客户的重要纽带,在工作中,以快速送餐突出业务能力:工作之余,他们会通过玩智力 ...

  7. MySQL 8.0 Command Line Client 不能打开或者闪退

    今天遇到了一个很奇怪的问题,就是在cmd窗口数据库可以正常访问然后MySQL 8.0 Command Line Client 打开或者闪退.有可能是缺少my.ini,但是我的是自己写过的,然后又查看了 ...

  8. oracle闪回某个时间点的数据库,Oracle 闪回总结

    一.闪回查询(Flashback Query) 1.闪回查询技术 1.1 闪回查询机制 闪回查询是指利用数据库回滚段存放的信息查看指定表中过去某个时间点的数据信息,或过去某个时间段数据的变化情况,或某 ...

  9. 美团外卖红包优惠券:美团外卖节红包或美团外卖天天神券怎么领取使用?

    什么是美团外卖节红包或美团外卖天天神券? 美团外卖节红包.美团外卖天天神券都可以称为美团外卖红包优惠券.使用美团外卖节红包.美团外卖天天神券,点餐可以享受优惠.且美团外卖节红包.美团外卖天天神券每天都 ...

最新文章

  1. 微信小程序 java 传值_微信小程序传值获取值的实例方法
  2. linux中设置默认权限的命令,Linux默认权限掩码
  3. #前端# 解决前端页面滑动不顺畅的问题
  4. tftp的安装、设置以及put、get传输实验
  5. js实现sqrt开方函数(二分法)
  6. 洛谷——P1927 防护伞
  7. python如何爬取图片到指定文件夹论文_基于Python的图片爬虫程序设计
  8. TensorFlow基础篇(四)—— tf.nn.relu()
  9. 机器学习的分类与主要算法
  10. 奔图 Pantum P2206NW 打印机驱动
  11. 5.用转换器抽取特征
  12. 苹果退款_苹果如何退款
  13. 比较两个字符串s1和s2的大小,如果s1s2,则输出一个正数;若s1=s2,则输出0;若s1小于s2,则输出一个负数。要求:不用strcpy函数;两个字符串用gets函数读入。
  14. 华为实验28-WAN接入配置
  15. logrotate实现日志切割和清理(清晰易懂)
  16. 手机号号码段及js验证
  17. oracle19c克隆PDB
  18. 判断两个圆柱体是否相交
  19. thunderbird备份_如何使用Thunderbird备份基于Web的电子邮件帐户
  20. QT开发之调用其它类中的UI控件的方法

热门文章

  1. Java Stub 研究学习(2)
  2. BZOJ 3870: Our happy ending( 状压dp )
  3. android 高级画布绘图
  4. 翻译: Waf 教程
  5. oracle 基础1
  6. WINCE的内存配置
  7. softmax函数理解
  8. android多线程下载原理,安卓多线程断点续传下载功能(靠谱第三方组件,原理demo)...
  9. java 内部类 返回值_Java基础第10天+形式参数和返回值的问题、包、导包、权限修饰符、常见的修饰符、内部类(局部内部类,成员内部类,匿名内部类)...
  10. linux添加自己的库,Linux学习笔记——例叙makefile 增加自定义共享库