Native flashback

更新时间:
复制 MD 格式

Native flashback lets you query or restore data to a specific point in time by using SQL statements, enabling fast recovery from accidental operations.

Overview

Accidental operations during database maintenance can severely impact your business. Traditional recovery methods such as Binlog Flashback are complex, error-prone, and time-consuming. Restoring from a backup set requires additional system resources, and recovery time becomes unpredictable for large data volumes.

AliSQL introduces native flashback for the InnoDB engine, eliminating complex recovery operations. With simple SQL statements, you can query or restore historical data from before an accidental operation, reducing recovery time and minimizing business impact.

Prerequisites

Your instance must run one of the following database versions. If the minor engine version does not meet the requirements, you can update it.

  • MySQL 8.4

  • MySQL 8.0 with a minor engine version of 20210930 or later.

Limitations

  • Only InnoDB engine tables are supported.

  • This feature consumes additional undo tablespace. You can limit the maximum size with the innodb_undo_space_supremum_size parameter.

  • A native flashback query returns data from the point in time closest to the specified timestamp. An exact match is not guaranteed.

  • Querying and restoring historical data across DDL operations is not supported. For example, you cannot use native flashback to query the content of a table that has been dropped.

Syntax

Native flashback introduces the AS OF clause to specify the point in time to query or restore. The syntax is as follows:

SELECT ... FROM <table_name>
  AS OF TIMESTAMP <expression>;

The expression specifies the target point in time and supports multiple formats. Examples:

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);

Parameters

The following parameters control native flashback behavior:

Parameter

Description

innodb_rds_flashback_task_enabled

  • Description: Enables or disables the native flashback feature.

  • Command-line format: --innodb-rds-flashback-task-enabled=#.

  • Scope: global parameter.

  • Data type: Boolean.

  • Default value: OFF.

  • Valid values: [ON|OFF].

Note

When you disable the native flashback feature, you must also set the innodb_undo_retention parameter to 0.

innodb_undo_retention

  • Description: The retention period for undo records, in seconds. Undo records older than this period cannot be queried.

  • Command-line format: --innodb-undo-retention=#.

  • Scope: global parameter.

  • Data type: Integer.

  • Default value: 0.

  • Valid values: 0 to 4294967295.

Note
  • A larger value allows native flashback to query further back in time but also increases the storage space consumed by the undo tablespace.

  • When the innodb_rds_flashback_task_enabled parameter is set to OFF, you must also set this parameter to 0.

innodb_undo_space_supremum_size

  • Description: The maximum size of the undo tablespace, in MB. If the space usage exceeds this value, undo records are forcibly purged, regardless of the innodb_undo_retention parameter setting.

  • Command-line format: --innodb-undo-space-supremum-size=#.

  • Scope: global parameter.

  • Data type: Integer.

  • Default value: 10240.

  • Valid values: 0 to 4294967295.

innodb_undo_space_reserved_size

  • Description: The reserved size, in MB, for the undo tablespace. When the innodb_undo_retention parameter is non-zero, this space is used to retain as many undo records as possible.

  • Command-line format: --innodb-undo-space-reserved-size=#.

  • Scope: global parameter.

  • Data type: Integer.

  • Default value: 0.

  • Valid values: 0 to 4294967295.

Note

A large value can cause excessive undo record accumulation, which impacts instance performance. Keep this parameter at 0 unless required.

Examples

# Get the current timestamp.
MySQL [mytest]> select now();
+---------------------+
| now()               |
+---------------------+
| 2020-10-14 15:44:09 |
+---------------------+
1 row in set (0.00 sec)

# View the data.
MySQL [mytest]> select * from mt1;
+----+------+
| id | c1   |
+----+------+
|  1 |    1 |
|  2 |    2 |
|  3 |    3 |
|  4 |    4 |
|  5 |    5 |
+----+------+
5 rows in set (0.00 sec)

# Run an update operation without a WHERE clause.
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)

# Query the historical data at the specified point in time. The query returns the expected result.
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)

# If the specified time is outside the retention window for historical data, the query fails.
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

# Start the data recovery.
MySQL [mytest]> create table mt1_tmp like mt1; # Create a temporary table with the same structure as the original table.
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'; # Insert the historical data from the original table into the temporary table. 
Query OK, 5 rows affected (0.01 sec) 
Records: 5  Duplicates: 0  Warnings: 0 
MySQL [mytest]> select * from mt1_tmp; # Verify that the data in the temporary table is correct. 
+----+------+
| 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; # (Before you perform this operation, stop all read and write operations on the table.) Rename the original table to mt1_bak and the temporary table to mt1 to complete the data recovery.
Query OK, 0 rows affected (0.02 sec)
MySQL [mytest]> select * from mt1; # Verify the restored data. 
+----+------+
| id | c1   |
+----+------+
|  1 |    1 |
|  2 |    2 |
|  3 |    3 |
|  4 |    4 |
|  5 |    5 |
+----+------+ 
5 rows in set (0.01 sec)