手机怎么做微电影网站,网络工程规划与设计案例,网站推广软件哪个好,网页制作素材教学由于运维、DBA的误操作或是业务bug#xff0c;我们在操作中时不时会出现误删除数据情况。早期要想恢复数据#xff0c;只能让业务人员根据线上操作日志#xff0c;构造误删除的数据#xff0c;或者DBA使用binlog和备份的方式恢复数据#xff0c;不管那种#xff0c;都非常… 由于运维、DBA的误操作或是业务bug我们在操作中时不时会出现误删除数据情况。早期要想恢复数据只能让业务人员根据线上操作日志构造误删除的数据或者DBA使用binlog和备份的方式恢复数据不管那种都非常费时费力而且容易出错。直到彭立勋首次在MySQL社区为mysqlbinlog扩展了闪回功能。 在美团点评我们也遇到过研发人员误删主站的配置信息从而导致主站长达2个小时不可用的情况。DBA同学当时使用了技术团队自研的binlog2sql完成了数据恢复并多次挽救了线上误删数据导致的严重故障。不过binlog2sql在恢复速度上不尽如人意因此我们开发了一个新的工具——MyFlash它很好地解决了上述痛点能够方便并且高效地进行数据恢复。 现在该工具正式开源开源地址为https://github.com/Meituan-Dianping/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 13 SET 113;binlog event回滚 根据上面的binlog介绍可以看到每个binlog event中event header有个type_code其中insert为30update为31delete为32。对于insert和delete两个相反的操作只需把type_code互换则在binlog event级别完成回滚。 而对于update操作其格式如下。 其中BI是指before imageAI是指after image。 我们只需依次遍历修改前的数据和修改后的数据并一一互换即可。因此整个回滚操作的难点在于回滚update语句而update语句回滚的核心在于计算出每个AI、BI的长度。下面介绍下长度以及部分字段的计算方法。 镜像长度计算 镜像是由一个个字段组成的根据字段类型的不同其计算长度的方法也不一样。 只与字段类型相关。比如int占用4个字节bingint占用8个字节。其中类型信息可以从table map event中获取。与字段类型及其参数相关。比如decimal189占用9个字节参数信息在table map event中。与字段类型、参数以及实际存储的值相关。比如varchar10有1个字节表示长度之后的字节才表示真正的数据。比如varchar280有2个字节表示长度。实际的长度和数据在一起。解析binlog中的若干个关键点 ① length encoded integer binlog中一个或者多个字节组合分别表示了不同的含义。比如timestamp是由固定的4个字节组成event类型由一个字节表示数据库名和表名最长为64个字符即使每个字符占用3个字节那么占用的字节数为192255。因此最多使用一个字节就可以完成实际长度表示。 然而列的实际数量可能需要超过1个字节、2个字节、3个字节甚至8个字节去表示。如果我们使用最大的8个字节去表示那么在绝大多数情况下都是浪费存储空间的。针对这种情况length encoded integer应运而生。 比如在获取一个varchar类型的长度时首先读取第一个字节如果值小于251那么varchar的长度就是第一个字节表示的长度。如果第一个字节的值为0xFC那么varchar的长度是由该字节之后的后两个字节组成以此类推。 ② decimal类型 decimal是由整数部分和小数部分组成。无论是整数还是小数每9个数字需要4个字节。如果不是9的倍数剩余的小数位需要的字节数如下为方便描述将该关系定义为函数Fnum。 举例对于 decimal18,10 整数部分可展示的为8用int即4个字节。小数部分需要的字节数为 (10 /9)*4Fnum(10%9)5。那么总共加起来需要459个字节。在上面的章节中介绍了单个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)
) ENGINEInnoDBmysql select count(*) from testFlashback2;
----------
| count(*) |
----------
| 1048576 |
----------
1 row in set (0.16 sec)delete from testFlashback2;测试结果 从上述图表中可以看出MyFlash的速度最快。 MySQL官方文档1,2,3.binlog2sql.mysqlbinlog Flashback for 5.6.MySQL闪回原理与实战.