TiDB恢复被误删除的数据或表

0    282    4

Tags:

👉 本文共约4358个字,系统预计阅读时间或需17分钟。

概述

TiDB恢复被误删除的数据或表

TiDB恢复被误删除的数据或表

FLASHBACK TABLE

参考:https://docs.pingcap.com/zh/tidb/stable/sql-statement-flashback-table/

在 TiDB 4.0 中,引入了 FLASHBACK TABLE 语法,其功能是在 Garbage Collection (GC) life time 时间内,可以用 FLASHBACK TABLE 语句来恢复被 DROPTRUNCATE 删除的表以及数据。

可以使用系统变量 tidb_gc_life_time 配置数据的历史版本的保留时间(默认值是 10m0s)。可以使用以下 SQL 语句查询当前的 safePoint,即 GC 已经清理到的时间点:

只要被 DROPTRUNCATE 删除的表是在 tikv_gc_safe_point 时间之后,都能用 FLASHBACK TABLE 语法来恢复。

注意事项

如果删除了一张表并过了 GC lifetime,就不能再用 FLASHBACK TABLE 语句来恢复被删除的数据了,否则会返回错误,错误类似于 Can't find dropped/truncated table 't' in GC safe point 2020-03-16 16:34:52 +0800 CST

在开启 TiDB Binlog 时使用 FLASHBACK TABLE 需要注意以下情况:

  • 下游从集群也支持 FLASHBACK TABLE
  • 从集群的 GC lifetime 一定要长于主集群的 GC lifetime。上下游同步存在的延迟可能也会造成下游恢复数据失败。

如果 Binlog 同步出错,则需要在 Binlog 过滤掉该表,同时手动全量重新导入该表的数据。

工作原理

TiDB 在删除表时,实际上只删除了表的元信息,并将需要删除的表数据(行数据和索引数据)写一条数据到 mysql.gc_delete_range 表。TiDB 后台的 GC Worker 会定期从 mysql.gc_delete_range 表中取出超过 GC lifetime 相关范围的 key 进行删除。

所以,FLASHBACK TABLE 只需要在 GC Worker 还没删除表数据前,恢复表的元信息并删除 mysql.gc_delete_range 表中相应的行记录即可。恢复表的元信息可以用 TiDB 的快照读实现。具体的快照读内容可以参考读取历史数据文档。下面是 FLASHBACK TABLE t TO t1 的工作流程:

  1. 从 DDL History job 中查找 drop table 或者 truncate table 类型的操作,且操作的表名是 t 的第一个 DDL job,若没找到,则返回错误。
  2. 检查 DDL job 的开始时间,是否在 tikv_gc_safe_point 之前。如果是tikv_gc_safe_point 之前,说明被 DROPTRUNCATE 删除的表已经被 GC 清理掉,返回错误。
  3. 用 DDL job 的开始时间作为 snapshot 读取历史数据,读取表的元信息。
  4. 删除 mysql.gc_delete_range 中和表 t 相关的 GC 任务。
  5. 将表的元信息中的 name 修改成 t1,并用该元信息新建一个表。注意:这里只是修改了表名,但是 table ID 不变,依旧是之前被删除的表 t 的 table ID。

可以发现,从表 t 被删除,到表 tFLASHBACK 恢复到 t1,一直都是对表的元信息进行操作,而表的用户数据一直未被修改过。被恢复的表 t1 和之前被删除的表 t 的 table ID 相同,所以表 t1 才能读取表t 的用户数据。

注意:

不能用 FLASHBACK 多次恢复同一个被删除的表,因为 FLASHBACK 所恢复表的 table ID 还是被删除表的 table ID,而 TiDB 要求所有还存在的表 table ID 必须全局唯一。

FLASHBACK TABLE 是通过快照读获取表的元信息后,再走一次类似于 CREATE TABLE 的建表流程,所以 FLASHBACK TABLE 实际上也是一种 DDL 操作。

RECOVER TABLE

参考:https://docs.pingcap.com/zh/tidb/stable/sql-statement-recover-table/#recover-table

RECOVER TABLE 的功能是恢复被删除的表及其数据。在 DROP TABLE 后,在 GC life time 时间内,可以用 RECOVER TABLE 语句恢复被删除的表以及其数据。

语法:

注意事项

如果删除表后并过了 GC lifetime,就不能再用 RECOVER TABLE 来恢复被删除的表了,执行 RECOVER TABLE 语句会返回类似错误:snapshot is older than GC safe point 2019-07-10 13:45:57 +0800 CST

对于 3.0.0 及之后的 TiDB 版本,不推荐在使用 TiDB Binlog 的情况下使用 RECOVER TABLE 功能。

TiDB Binlog 在 3.0.1 支持 RECOVER TABLE 后,可在下面的情况下使用 RECOVER TABLE

  • 3.0.1+ 版本的 TiDB Binlog
  • 主从集群都使用 TiDB 3.0
  • 从集群 GC lifetime 一定要长于主集群(不过由于上下游同步的延迟,可能也会造成下游 recover 失败)

TiDB Binlog 同步错误处理

当使用 TiDB Binlog 同步工具时,上游 TiDB 使用 RECOVER TABLE 后,TiDB Binlog 可能会因为下面几个原因造成同步中断:

  • 下游数据库不支持 RECOVER TABLE 语句。类似错误:check the manual that corresponds to your MySQL server version for the right syntax to use near 'RECOVER TABLE table_name'
  • 上下游数据库的 GC lifetime 不一样。类似错误:snapshot is older than GC safe point 2019-07-10 13:45:57 +0800 CST
  • 上下游数据库的同步延迟。类似错误:snapshot is older than GC safe point 2019-07-10 13:45:57 +0800 CST

只能通过重新全量导入被删除的表来恢复 TiDB Binlog 的数据同步。

示例

  • 根据表名恢复被删除的表。

    根据表名恢复被删除的表需满足以下条件:

    • 最近 DDL JOB 历史中找到的第一个 DROP TABLE 操作,且
    • DROP TABLE 所删除的表的名称与 RECOVER TABLE 语句指定表名相同
  • 根据删除表时的 DDL JOB ID 恢复被删除的表。

    如果第一次删除表 t 后,又新建了一个表 t,然后又把新建的表 t 删除了,此时如果想恢复最开始删除的表 t, 就需要用到指定 DDL JOB ID 的语法了。

    上面这个语句用来查找删除表 t 时的 DDL JOB ID,这里是 53:

    根据删除表时的 DDL JOB ID 恢复被删除的表,会直接用 DDL JOB ID 找到被删除表进行恢复。如果指定的 DDL JOB ID 的 DDL JOB 不是 DROP TABLE 类型,会报错。

原理

TiDB 在删除表时,实际上只删除了表的元信息,并将需要删除的表数据(行数据和索引数据)写一条数据到 mysql.gc_delete_range 表。TiDB 后台的 GC Worker 会定期从 mysql.gc_delete_range 表中取出超过 GC lifetime 相关范围的 key 进行删除。

所以,RECOVER TABLE 只需要在 GC Worker 还没删除表数据前,恢复表的元信息并删除 mysql.gc_delete_range 表中相应的行记录就可以了。恢复表的元信息可以用 TiDB 的快照读实现。具体的快照读内容可以参考读取历史数据文档。

TiDB 中表的恢复是通过快照读获取表的元信息后,再走一次类似于 CREATE TABLE 的建表流程,所以 RECOVER TABLE 实际上也是一种 DDL。

示例

truncate示例

示例一:

示例二:

通过设置 tidb_snapshot 参数来读取历史数据,并用到 dumpling --snapshot 和FLASHBACK TABLE 恢复被多次 TRUNCATE 的数据。

  1. 初始化环境:

  1. 模拟误 Truncate 表:

  1. 数据恢复目标: 分别将第一次以及第二次 Truncate 前的数据找到,并恢复到原表 trun_tab 中。

  2. 确认是否满足 GC 要求: admin show ddl jobs 查看两次 Truncate 操作发生的时间

    • 第一次:2022-01-04 11:18:19
    • 第二次:2022-01-04 11:18:37

查看当前 GC 保留的 safe point,此处为 20220104-11:06:38 +0800,并且满足恢复要求:

如果满足,那么调整 GC interval time,避免数据的 MVCC 历史版本被清理掉,影响数据恢复,此处为 720h:

  1. 开始恢复数据: 设置 tidb_snapshot 为数据更改前的时间点,此处为 "2022-01-04 11:18:18",小于第一次Truncate 时间为 "2022-01-04 11:18:19"

恢复第一次 Truncate 的数据: 因为 Flashback 语句无法与 set tidb_snapshot 一起使用,即无法使用 Flashback 多次恢复同
一张表。
ERROR 1105 (HY000): can not execute write statement when 'tidb_snapshot' is seted.

使用 dumpling 备份目标 trun_tab 表数据,snapshot 的时间点为 "2022-01-04 11:18:18":

应用第一次 Truncate 前的数据到 trun_tab 表:

本人提供Oracle、MySQL、PG等数据库的培训和考证业务,私聊QQ646634621或微信db_bao,谢谢!
  1. 恢复第二次 Truncate 的数据: Flashback trun_tab 第二次 Truncate 前的数据到 trun_tab_02 中:

至此两次数据恢复均完成,反馈执行结果给『业务端』,并确认二次恢复的结果。

drop示例

tidb_snapshot 读取历史数据并恢复

开始数据恢复,设置 tidb_snapshot 为数据更改前的时间点,

反馈查询结果给『业务端』,并且确认是否满足恢复目标

  • 满足,那么继续下面的操作步骤
  • 不满足,那么继续反复修改 tidb_snapshot,查看历史数据是否满足数据恢复需求
    根据 tidb_snapshot 的查询结果生成反向 SQL。

清空当前 session tidb_snapshot 变量,然后进行恢复:

调整 GC interval time 为原值:

标签:

头像

小麦苗

学习或考证,均可联系麦老师,请加微信db_bao或QQ646634621

您可能还喜欢...

发表回复

嘿,我是小麦,需要帮助随时找我哦
  • 18509239930
  • 个人微信

  • 麦老师QQ聊天
  • 个人邮箱
  • 点击加入QQ群
  • 个人微店

  • 回到顶部
返回顶部