基于Drainer的TiDB的闪回实现

背景

由于运维、DBA的误操作或是业务bug,我们在操作中不可避免的会出现误删除数据情况。目前,TiDB只提供了类似oralce的 Flashback Query,详细说明参见TiDB 历史数据回溯。但其查询时间受限与GC且不能生成闪回SQL。延长GC的时间,则存在以下问题:

  • 磁盘空间占用较多
  • 大量的历史版本会在一定程度上影响性能,尤其是范围查询(如 select count(*) from t

对于MySQL DBA来说,有很多基于binlog实现的开源的闪回工具,如binlog2sql、MyFlash。TiDB也提供了类似MySQL的binlog,因此可以基于类似的方法实现TiDB的闪回。

TiDB Binlog

TiDB Binlog 集群主要分为 Pump 和 Drainer 两个组件,以及 binlogctl 工具:

Pump

Pump用于实时记录 TiDB 产生的 Binlog,并将 Binlog 按照事务的提交时间进行排序,再提供给 Drainer 进行消费。

Drainer

Drainer 从各个 Pump 中收集 Binlog 进行归并,再将 Binlog 转化成 SQL 或者指定格式的数据,最终同步到下游。

binlogctl 工具

binlogctl 是一个 TiDB Binlog 配套的运维工具,具有如下功能:

  • 获取 TiDB 集群当前的 TSO
  • 查看 Pump/Drainer 状态
  • 修改 Pump/Drainer 状态
  • 暂停/下线 Pump/Drainer

binlog的格式介绍参见TiDB Binlog 源码解析

方案介绍

从上面关于TiDB Binlog的介绍中,我们知道Drainer从各个Pump收集Binlog进行归并,再将Binlog进行转换。 从drainer的配置文件中,可以看到下游服务类型有四种,

-dest-db-type string
    Drainer 下游服务类型 (默认为 mysql,支持 tidb、kafka、file)

因此,可以通过新增加一种下游服务类型来实现flashback。

参数介绍

相较drainer,新增了几个参数,同时对之前的dest-db-type做了类型的扩充

  -dest-db-type string
    	target db type: mysql or tidb or file or kafka or flashback; see syncer section in conf/drainer.toml (default "mysql")
  -do-dml string
    	do-dml : insert ,update ,delete ; you can choose more than one ,default all dmls
  -end-time string
    	flashback end in end-time, empty string means never end.
  -end-tso int
    	similar to end-time, but in pd-server tso format
  -start-time string
    	flashback from start-time, empty string means starting from current time
  -start-tso int
    	similar to start-time but in pd-server tso format

实现原理

1、新增一个syncer类

在createDSyncer函数中新增NewFlashBackSyncer,相较其他的syncer函数,增加了限制参数,如start-time、do-dml等,而对相关库表的过滤,依赖与drainer之前实现的过滤方法

2、将tidb的binlog改成闪回用的binlog

这块的改写逻辑类似与MySQL的闪回改写逻辑,详情参见闪回思路

3、新增对tidb binlog生成语句的函数

通过新增的ToOriginalSQL和ToFlashBackSQL,生成原始和闪回的SQL

操作

实际使用和drainer没有太大区别,如:

drainer -pd-urls https://127.0.0.1:2379 -dest-type flashback -start-time "209-12-25 00:00:00" -end-time "2019-12-25 10:00:00"

操作结果会产生三类文件:闪回的binlog文件、原始SQL文件、闪回SQL文件,闪回的binlog文件可以直接使用reparo进行操作。

上面简单讲解了闪回工具的实现,后续这块会作为PR提交给官方,到时欢迎吐槽和拍砖。

1赞