Native Flashback

Native Flashback功能可以通过SQL语句查询或恢复指定时间点的数据,保证在误操作后可以快速获取历史数据。在数据库运维中,误更新或误删除数据等操作可能导致业务中断。传统的恢复方法,如使用Binlog或备份集,过程复杂且耗时较长。PolarDB-X 2.0标准版提供Native Flashback功能,您仅需通过简单的SQL语句,即可查询指定时间点的历史数据或将数据快速恢复到误操作发生前的状态,从而最大程度地减少业务损失。

功能说明

Native FlashbackPolarDB-X 2.0标准版基于InnoDB引擎实现的一项功能。它通过保留特定时间范围内的undo日志,使您能够查询这些历史版本的数据。当发生数据误操作时,您无需进行复杂的操作,即可利用AS OF语法快速查询历史数据,并根据需要将其恢复,实现秒级数据闪回。

适用范围

  • 实例版本:PolarDB-X 2.0标准版

  • 引擎版本:MySQL 8.0

  • 存储引擎:InnoDB

注意事项

  • Native Flashback功能需要消耗额外的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功能开放了如下可配置参数,您可在PolarDB分布式版控制台配置与管理 > 参数设置页面中进行修改。

参数名称

说明

innodb_undo_retention

  • 描述:undo记录的保留时长,超出该时长的undo记录无法查询。

  • 命令行格式:--innodb-undo-retention=#。

  • 参数范围:全局参数。

  • 数据类型:Integer。

  • 取值范围:0~4294967295。

  • 单位:秒。

  • 默认值:300。

说明

该参数的值越大,Native Flashback支持的回档查询时间越长,同时undo表空间占用的存储空间也会增加。

innodb_undo_space_supremum_size

  • 描述:undo表空间可占用的最大磁盘空间。占用空间超过这个值时,忽略innodb_undo_retention参数强制清理undo记录。

  • 命令行格式:--innodb-undo-space-supremum-size=#。

  • 参数范围:全局参数。

  • 数据类型:Integer。

  • 取值范围:0~4294967295。

  • 单位:MB。

  • 默认值:102400。

innodb_undo_space_reserved_size

  • 描述:预留的undo表空间大小。在innodb_undo_retention参数非0的情况下,将使用这部分空间尽可能多地保留undo记录。

  • 命令行格式:--innodb-undo-space-reserved-size=#。

  • 参数范围:全局参数。

  • 数据类型:Integer。

  • 取值范围:0~4294967295。

  • 单位:MB。

  • 默认值:0。

说明

该参数的值太大可能导致undo历史记录过多,影响实例性能。如非必要,请保持该参数为0。

使用示例

  1. 准备测试数据。

    CREATE TABLE flashback_test (
        id INT PRIMARY KEY,
        name VARCHAR(50)
    );
    
    INSERT INTO flashback_test VALUES (1, 'Alice'), (2, 'Bob'), (3, 'Charlie');
  2. 查看原数据。

    SELECT * FROM flashback_test;
    
    -- 查询结果
    +----+---------+
    | id | name    |
    +----+---------+
    |  1 | Alice   |
    |  2 | Bob     |
    |  3 | Charlie |
    +----+---------+
    3 rows in set (0.00 sec)
  3. 获取当前时间点。

    SELECT now();
    
    -- 查询结果
    +---------------------+
    | now()               |
    +---------------------+
    | 2025-09-25 10:54:48 |
    +---------------------+
    1 row in set (0.00 sec)
  4. 更新数据,模拟误操作。

    UPDATE flashback_test SET name = 'DELETED';
    
    -- 查询数据
    SELECT * FROM flashback_test;
    
    -- 查询结果
    +----+---------+
    | id | name    |
    +----+---------+
    |  1 | DELETED |
    |  2 | DELETED |
    |  3 | DELETED |
    +----+---------+
    3 rows in set (0.00 sec)
  5. 查询历史时间点的数据,成功返回结果。

    SELECT * FROM flashback_test AS OF timestamp '2025-09-25 10:54:48';
    
    -- 查询结果
    +----+---------+
    | id | name    |
    +----+---------+
    |  1 | Alice   |
    |  2 | Bob     |
    |  3 | Charlie |
    +----+---------+
    3 rows in set (0.00 sec)

    若查询超出保留的历史数据范围(默认5分钟)或表进行过DDL操作,则会返回失败。

    -- 超出保留的历史数据范围
    ERROR 7510 (HY000): Snapshot too old
    
    -- 进行过DDL操作
    ERROR 7509 (HY000): The definition of the table required by the flashback query has changed
  6. 恢复数据。

    说明

    以下整表恢复操作仅作为示例。在实际数据恢复过程中,若您能够确定误操作的具体数据,请根据实际情况选择批量或逐行进行恢复。

    1. 创建一个与原表结构相同的临时表。

      CREATE TABLE flashback_test_tmp LIKE flashback_test;
    2. 将原表中的历史数据写入临时表。

      INSERT INTO flashback_test_tmp SELECT * FROM flashback_test AS OF timestamp '2025-09-25 10:54:48';
    3. 确认临时表中的数据是否正确 .

      -- 查询数据
      SELECT * FROM flashback_test_tmp;
      
      -- 查询结果
      +----+---------+
      | id | name    |
      +----+---------+
      |  1 | Alice   |
      |  2 | Bob     |
      |  3 | Charlie |
      +----+---------+
      3 rows in set (0.00 sec)
    4. 更改原表表名为flashback_test_bak,并将临时表名改成原表表名,完成数据恢复。

      说明

      进行此操作时,需要先停止业务对当前表的读写。

      -- 变更原表名,临时表变更为原表
      RENAME TABLE flashback_test TO flashback_test_bak, flashback_test_tmp to flashback_test;
    5. 确认恢复完成后的数据。

      -- 查询数据
      SELECT * FROM flashback_test;
      
      -- 查询结果
      +----+---------+
      | id | name    |
      +----+---------+
      |  1 | Alice   |
      |  2 | Bob     |
      |  3 | Charlie |
      +----+---------+
      3 rows in set (0.00 sec)