首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >TiDB的闪回

TiDB的闪回

作者头像
薛晓刚-
发布2026-06-25 10:24:43
发布2026-06-25 10:24:43
110
举报

经历过Oracle的闪回都觉得这是一个救命的功能

  • MySQL数据库要想实现这个功能,需要做很多人工的操作。
  • 很多数据库都可以利用日志、实时备份、延迟复制等各种组合拳解决Drop table的问题。
  • 这就使得类似闪回的功能非常人性化了

Oracle的闪回这里不介绍了

  • 能找过过去一定时间内的数据或者drop的表。

看看TiDB的闪回

  • mysql> select * from xxg limit 10; ±—±-------±-----+ | id | m | n | ±—±-------±-----+ | 1 | Window | 1600 | | 2 | Window | 1600 | | 3 | Window | 1600 | | 4 | Window | 1600 | | 5 | Window | 602 | | 6 | Window | 1600 | | 7 | Window | 602 | | 8 | Window | 1600 | | 9 | Window | 602 | | 10 | Window | 1600 | ±—±-------±-----+ 10 rows in set (0.00 sec)
  • 抽样获取10行数据。

mysql> select now(); ±--------------------+ | now() | ±--------------------+ | 2025-06-09 16:13:38 | ±--------------------+ 1 row in set (0.00 sec)

  • 获取当前时间

mysql> delete from xxg where id=1; Query OK, 1 row affected (0.01 sec)

  • 删除ID=1的一行数据

mysql> select now(); ±--------------------+ | now() | ±--------------------+ | 2025-06-09 16:14:18 | ±--------------------+ 1 row in set (0.01 sec)

  • 获取当前时间

mysql> update xxg set n=300 where id=2; Query OK, 1 row affected (0.02 sec) Rows matched: 1 Changed: 1 Warnings: 0

  • 更新ID=2的一行数据

mysql> select now(); ±--------------------+ | now() | ±--------------------+ | 2025-06-09 16:14:43 | ±--------------------+ 1 row in set (0.00 sec)

mysql> select * from xxg limit 10; ±—±-------±-----+ | id | m | n | ±—±-------±-----+ | 2 | Window | 300 | | 3 | Window | 1600 | | 4 | Window | 1600 | | 5 | Window | 602 | | 6 | Window | 1600 | | 7 | Window | 602 | | 8 | Window | 1600 | | 9 | Window | 602 | | 10 | Window | 1600 | | 11 | Window | 1600 | ±—±-------±-----+ 10 rows in set (0.01 sec)

  • 现在数据已经改变了。接下来要看闪回能做什么和不能做什么了。

mysql> select * from xxg as of timestamp ‘2025-06-09 16:12:50’ limit 10; ±—±-------±-----+ | id | m | n | ±—±-------±-----+ | 1 | Window | 1600 | | 2 | Window | 1600 | | 3 | Window | 1600 | | 4 | Window | 1600 | | 5 | Window | 602 | | 6 | Window | 1600 | | 7 | Window | 602 | | 8 | Window | 1600 | | 9 | Window | 602 | | 10 | Window | 1600 | ±—±-------±-----+ 10 rows in set (0.01 sec)

  • 可以查询到最开始的数据状态。

mysql> select * from xxg as of timestamp ‘2025-06-09 16:14:30’ limit 10; ±—±-------±-----+ | id | m | n | ±—±-------±-----+ | 2 | Window | 1600 | | 3 | Window | 1600 | | 4 | Window | 1600 | | 5 | Window | 602 | | 6 | Window | 1600 | | 7 | Window | 602 | | 8 | Window | 1600 | | 9 | Window | 602 | | 10 | Window | 1600 | | 11 | Window | 1600 | ±—±-------±-----+ 10 rows in set (0.01 sec)

  • 也可以查询到只删除一条数据的时间点的状态。

mysql> select * from xxg as of timestamp ‘2025-06-09 16:14:50’ limit 10; ±—±-------±-----+ | id | m | n | ±—±-------±-----+ | 2 | Window | 300 | | 3 | Window | 1600 | | 4 | Window | 1600 | | 5 | Window | 602 | | 6 | Window | 1600 | | 7 | Window | 602 | | 8 | Window | 1600 | | 9 | Window | 602 | | 10 | Window | 1600 | | 11 | Window | 1600 | ±—±-------±-----+ 10 rows in set (0.00 sec)

mysql> select * from xxg limit 10; ±—±-------±-----+ | id | m | n | ±—±-------±-----+ | 2 | Window | 300 | | 3 | Window | 1600 | | 4 | Window | 1600 | | 5 | Window | 602 | | 6 | Window | 1600 | | 7 | Window | 602 | | 8 | Window | 1600 | | 9 | Window | 602 | | 10 | Window | 1600 | | 11 | Window | 1600 | ±—±-------±-----+ 10 rows in set (0.01 sec)

  • 当然最后时间也就是现在。

开始数据恢复

mysql> create table t1 as select * from xxg as of timestamp ‘2025-06-09 16:12:50’ limit 10; ERROR 1105 (HY000): ‘CREATE TABLE … SELECT’ is not implemented yet

  • 不支持我们传统的SQL

mysql> create table t1 as select * from xxg where 1=2; ERROR 1105 (HY000): ‘CREATE TABLE … SELECT’ is not implemented yet

  • 即使是做建立一个表结构这样也不行。

mysql> create table t1 as select * from xxg; ERROR 1105 (HY000): ‘CREATE TABLE … SELECT’ is not implemented yet mysql> mysql> show create table xxg\G *************************** 1. row *************************** Table: xxg Create Table: CREATE TABLExxg( idint NOT NULL AUTO_INCREMENT, mvarchar(10) DEFAULT NULL, nint DEFAULT NULL, PRIMARY KEY (id) /*T![clustered_index] CLUSTERED */ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin AUTO_INCREMENT=12329325 1 row in set (0.00 sec)

  • 只能根据原表的表结构,老老实实的建议个空表。

mysql> create table t1 ( -> id int NOT NULL AUTO_INCREMENT, -> m varchar(10) DEFAULT NULL, -> n int DEFAULT NULL, -> PRIMARY KEY (id)); Query OK, 0 rows affected (0.52 sec)

mysql> insert into t1 select * from xxg as of timestamp ‘2025-06-09 16:12:50’ limit 10; ERROR 8135 (HY000): can not set different time in the as of

  • 采用insert into的方法,不支持。
  • 需要用的命令是import into,这里注意后面还要带一个from。特殊的语法。

mysql> import into t1 from select * from xxg as of timestamp ‘2025-06-09 16:12:50’ limit 10; ERROR 9006 (HY000): GC life time is shorter than transaction duration, transaction starts at 2025-06-09 16:12:50 +0800 CST, GC safe point is 2025-06-09 16:24:55.441 +0800 CST

  • 终于解决了语法问题。带来了一个姓问题。显示生命时间太短。想起了我之前Oracle闪回建表的时候,ogg下游undo不足的场景。
  • 查到了数据保留时间,默认10分钟。我个人觉得的太短了。正式环境怎么也应该一个小时。

mysql> show variables like ‘tidb_gc_life_time’; ±------------------±------+ | Variable_name | Value | ±------------------±------+ | tidb_gc_life_time | 10m0s | ±------------------±------+ 1 row in set (0.00 sec)

  • 目前先按照10分钟的进行实践。

mysql> select now(); ±--------------------+ | now() | ±--------------------+ | 2025-06-09 16:50:44 | ±--------------------+ 1 row in set (0.00 sec)

mysql> delete from xxg where id<21; Query OK, 10 rows affected (0.01 sec)

mysql> select now(); ±--------------------+ | now() | ±--------------------+ | 2025-06-09 16:50:58 | ±--------------------+ 1 row in set (0.00 sec)

mysql> select * from xxg where id<21; Empty set (0.01 sec)

mysql> select * from xxg where id<22; ±—±-------±-----+ | id | m | n | ±—±-------±-----+ | 21 | Window | 1600 | ±—±-------±-----+ 1 row in set (0.00 sec)

mysql> import into t1 from select * from xxg as of timestamp ‘2025-06-09 16:45:50’ where id<21; Query OK, 19 rows affected (0.92 sec) Records: 19, ID: e8fe2d19-0061-41a3-a4d0-6eab82fd6bbb

mysql> select * from t1; ±—±-------±-----+ | id | m | n | ±—±-------±-----+ | 2 | Window | 300 | | 3 | Window | 1600 | | 4 | Window | 1600 | | 5 | Window | 602 | | 6 | Window | 1600 | | 7 | Window | 602 | | 8 | Window | 1600 | | 9 | Window | 602 | | 10 | Window | 1600 | | 11 | Window | 1600 | | 12 | Window | 1600 | | 13 | Window | 602 | | 14 | Window | 1600 | | 15 | Window | 1600 | | 16 | Window | 1600 | | 17 | Window | 602 | | 18 | Window | 1600 | | 19 | Window | 602 | | 20 | Window | 1600 | ±—±-------±-----+ 19 rows in set (0.01 sec)

  • 闪回建表成功。
  • 下面尝试一下drop和truncate。Oracle的闪回是不支持truncate的。 mysql> select now(); ±--------------------+ | now() | ±--------------------+ | 2025-06-09 16:53:06 | ±--------------------+ 1 row in set (0.00 sec)

mysql> drop table t1; Query OK, 0 rows affected (0.52 sec)

mysql> truncate table t2; Query OK, 0 rows affected (0.52 sec)

mysql> select now(); ±--------------------+ | now() | ±--------------------+ | 2025-06-09 16:53:56 | ±--------------------+ 1 row in set (0.00 sec)

mysql> flashback table t1; Query OK, 0 rows affected (0.56 sec)

mysql> flashback table t2; ERROR 1050 (42S01): Table ‘t2’ already exists mysql> flashback table t2 to t3; Query OK, 0 rows affected (0.54 sec)

  • truncate的闪回要注意,表结构还在。不能直接flashback。需要重命名定向一下。

mysql> select * from t1; ±—±-------±-----+ | id | m | n | ±—±-------±-----+ | 2 | Window | 300 | | 3 | Window | 1600 | | 4 | Window | 1600 | | 5 | Window | 602 | | 6 | Window | 1600 | | 7 | Window | 602 | | 8 | Window | 1600 | | 9 | Window | 602 | | 10 | Window | 1600 | | 11 | Window | 1600 | | 12 | Window | 1600 | | 13 | Window | 602 | | 14 | Window | 1600 | | 15 | Window | 1600 | | 16 | Window | 1600 | | 17 | Window | 602 | | 18 | Window | 1600 | | 19 | Window | 602 | | 20 | Window | 1600 | ±—±-------±-----+ 19 rows in set (0.00 sec)

mysql> select * from t2; Empty set (0.00 sec)

mysql> select * from t3; ±—±-------±-----+ | id | m | n | ±—±-------±-----+ | 2 | Window | 300 | | 3 | Window | 1600 | | 4 | Window | 1600 | | 5 | Window | 602 | | 6 | Window | 1600 | | 7 | Window | 602 | | 8 | Window | 1600 | | 9 | Window | 602 | | 10 | Window | 1600 | | 11 | Window | 1600 | | 12 | Window | 1600 | | 13 | Window | 602 | | 14 | Window | 1600 | | 15 | Window | 1600 | | 16 | Window | 1600 | | 17 | Window | 602 | | 18 | Window | 1600 | | 19 | Window | 602 | | 20 | Window | 1600 | ±—±-------±-----+ 19 rows in set (0.01 sec)

  • 时间完毕

注意点

  • 闪回的生命周期
  • import的语法
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-06-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 四海内皆兄弟 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 经历过Oracle的闪回都觉得这是一个救命的功能
  • Oracle的闪回这里不介绍了
  • 看看TiDB的闪回
  • 开始数据恢复
  • 注意点
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档