Native Flashback功能可以通过SQL语句查询或恢复指定时间点的数据,保证在误操作后可以快速获取历史数据。
功能说明
数据库运维过程中的误操作可能会给业务带来严重的影响,常见的恢复手段Binlog Flashback操作较为复杂、容易出错且耗时较长,而通过备份集恢复则需要额外的系统资源,在数据量较大时恢复时间不可控。
AliSQL在InnoDB引擎上设计和实现了Native Flashback功能,无需复杂的恢复操作,通过简单的SQL语句即可查询或恢复误操作前的历史数据,节省了大量宝贵的时间,保证业务平稳运行。
前提条件
- 实例为RDS MySQL 8.0基础系列、高可用系列或集群系列。 
- 内核小版本为20210930及以上。如何查看或升级内核小版本,请参见升级内核小版本。 
注意事项
- 仅支持使用InnoDB引擎的表。 
- 需要消耗额外的undo表空间,可以通过innodb_undo_space_supremum_size参数进行配置。 
- Native Flashback的查询结果取最接近指定时间点的数据,不保证查询到的数据与指定时间点的数据完全匹配。 
- 暂不支持跨DDL操作的历史版本数据查询和恢复。例如您无法通过Native Flashback查询某个已经被删除的表的内容。 
语法
Native Flashback提供了全新的AS OF语法,通过该语法指定需要回滚的时间。语法规则如下:
SELECT ... FROM <表名>
  AS OF TIMESTAMP <表达式>;其中,在表达式中指定回滚的时间,该表达式支持多种形式,示例:
SELECT ... FROM tablename
  AS OF TIMESTAMP '2020-11-11 00:00:00';
SELECT ... FROM tablename
  AS OF TIMESTAMP now();
SELECT ... FROM tablename
  AS OF TIMESTAMP (SELECT now());
SELECT ... FROM tablename
  AS OF TIMESTAMP DATE_SUB(now(), INTERVAL 1 minute);参数说明
Native Flashback功能开放了如下可配置参数:
| 参数名称 | 说明 | 
| innodb_rds_flashback_task_enabled | 
 说明  关闭Native Flashback功能时,需要同步将innodb_undo_retention参数设置为0。 | 
| innodb_undo_retention | 
 说明  
 | 
| innodb_undo_space_supremum_size | 
 | 
| innodb_undo_space_reserved_size | 
 说明  该参数的值太大可能导致undo历史记录过多,影响实例性能。如非必要,请保持该参数为0。 | 
使用示例
# 获取时间点
MySQL [mytest]> select now();
+---------------------+
| now()               |
+---------------------+
| 2020-10-14 15:44:09 |
+---------------------+
1 row in set (0.00 sec)
# 查看数据
MySQL [mytest]> select * from mt1;
+----+------+
| id | c1   |
+----+------+
|  1 |    1 |
|  2 |    2 |
|  3 |    3 |
|  4 |    4 |
|  5 |    5 |
+----+------+
5 rows in set (0.00 sec)
# 不带WHERE条件的更新操作
MySQL [mytest]> update mt1 set c1 = 100;
Query OK, 5 rows affected (0.00 sec)
Rows matched: 5  Changed: 5  Warnings: 0
MySQL [mytest]> select * from mt1;
+----+------+
| id | c1   |
+----+------+
|  1 |  100 |
|  2 |  100 |
|  3 |  100 |
|  4 |  100 |
|  5 |  100 |
+----+------+
5 rows in set (0.00 sec)
# 查询历史时间点的数据,成功返回结果
MySQL [mytest]> select * from mt1 AS OF timestamp '2020-10-14 15:44:09';
+----+------+
| id | c1   |
+----+------+
|  1 |    1 |
|  2 |    2 |
|  3 |    3 |
|  4 |    4 |
|  5 |    5 |
+----+------+
5 rows in set (0.00 sec)
# 如果超出保留的历史数据范围,返回失败
MySQL [mytest]> select * from mt1 AS OF timestamp '2020-10-13 14:44:09';
ERROR 7545 (HY000): The snapshot to find is out of range
# 开始恢复数据
MySQL [mytest]> create table mt1_tmp like mt1; # 创建一个与原表结构相同的临时表
Query OK, 0 rows affected (0.03 sec)  
MySQL [mytest]> insert into mt1_tmp
             -> select * from mt1 AS OF
             -> TIMESTAMP '2020-10-14 15:44:09'; # 将原表中的历史数据写入临时表 
Query OK, 5 rows affected (0.01 sec) 
Records: 5  Duplicates: 0  Warnings: 0 
MySQL [mytest]> select * from mt1_tmp; # 确认临时表中的数据是否正确 
+----+------+
| id | c1   |
+----+------+
|  1 |    1 |
|  2 |    2 |
|  3 |    3 |
|  4 |    4 |
|  5 |    5 |
+----+------+
5 rows in set (0.00 sec) 
MySQL [mytest]> rename table mt1 to mt1_bak,
             -> mt1_tmp to mt1; #(进行本操作需要先停止业务读写)更改原表表名为mt1_bak,并将临时表名改成原表表名,完成数据恢复
Query OK, 0 rows affected (0.02 sec)
MySQL [mytest]> select * from mt1; # 确认恢复完成后的数据 
+----+------+
| id | c1   |
+----+------+
|  1 |    1 |
|  2 |    2 |
|  3 |    3 |
|  4 |    4 |
|  5 |    5 |
+----+------+ 
5 rows in set (0.01 sec)