更新时间:2025-10-27 GMT+08:00
分享

闪回查询

功能介绍

在客户数据误删除或漏洞引发数据异常、业务审计需追溯历史数据等场景下,数据库闪回功能成为客户的核心需求。传统基于Binlog的闪回方案存在强依赖Binlog,低效等局限。针对上述痛点,TaurusDB支持基于Undo log的表级闪回查询功能,其核心优势在于:

  • 内核级支持:直接利用UNDO表空间的历史数据镜像,无外部依赖。
  • 精准恢复能力:支持表级数据回滚到指定时间点,精确到0.1秒级别。
  • 支持单表闪回,无需保留闪回时间段内所有Undo log,只针对性保留闪回表的Undo log。

版本约束

  • TaurusDB实例内核版本大于等于2.0.69.250900,支持闪回查询。
  • 若TaurusDB实例内核版本等于2.0.69.250900,Undo tablespace的truncate与闪回Undo log异步truncate存在互斥,即undo truncate特性与innodb_rds_backquery_undo_async_trunc不能同时打开。
  • 在业务写入压力大时,Purge存在性能瓶颈。限制InnoDB History list长度可以缓解此瓶颈,具体做法如下:
    • 建议非IO型业务开启闪回。当History list过大可能触发InnoDB Buffer pool频繁页面换出时,InnoDB Purge性能将受较大影响。
    • 限制闪回时间窗口长度。在写业务压力大时,通过参数“innodb_rds_backquery_window”控制闪回时长,避免History list过长。

使用限制

  • 仅支持InnoDB引擎表,不支持其他视图和其他引擎表。
  • 不允许闪回时间窗口内发生DDL,尤其是DROP TABLE, TRUNCATE TABLEADD COLUMN, DROP COLUMNOPTIMIZE TABLE等会改变使用Cluster Index(聚簇索引)的操作,仅允许闪回表在闪回时间窗口内发生DML。
  • 闪回查询最低支持粒度为0.1秒级别。
  • 闪回查询仅支持使用主键索引,或者InnoDB为无主键表自动生成的主键GEN_CLUST_INDEX。
  • 不支持在Prepared statement(预处理语句)和Stored procedure(存储过程)中使用。
  • 不支持的复杂语句
    • CREATE TABLE AS ...
    • INSERT SELECT ...
    • REPLACE SELECT ...
  • 特性关闭再打开后,无法闪回到关闭前的时间。
  • “innodb_rds_backquery_enable”参数更改时,参数变更需要异步生效。如果在异步生效期间再次修改参数“innodb_rds_backquery_enable”,将报“The BACKQUERY state cannot be changed because the previous state modification is not yet complete" 错误。
  • 闪回查询不支持迁移场景。本特性基于Undo log实现。在迁移等场景创建的新实例中,由于缺少原实例的Undo log,无法通过闪回特性查询新实例创建之前的历史数据。

原理介绍

  1. Undo log的Purge流程:
    1. 第一轮Purge为原生InnoDB触发的Purge,使用的MVCC的m_views中最老的Readview,将彻底清理非闪回表的主键索引和二级索引,清理闪回表的二级索引,保留其聚簇索引。

      触发的来源包括:更新数据字典统计信息、崩溃恢复或原子DDL的撤销流程中、关闭undo tablespace时、InnoDB master线程中常规检查、事务提交时、通过设置参数手动开启或关闭Purge时、关闭MySQL进程时等等。

    2. 第二轮Purge为闪回后台线程触发的Purge,使用闪回系统最老的Readview(某一时刻的活跃事务列表),将彻底清理闪回表的主键索引。
  2. Undo log的Truncation(删除undo log)流程:
    1. 首先进行MVCC Truncation,删除不包含闪回表的Undo log。
    2. 其次进行闪回Truncation,删除包含闪回表的Undo log。

    MVCC Truncation和闪回Truncation没有先后关系,只负责在Readview范围内清理相应的Undo log。Undo log状态示意图如下:

    图1 Undo log Truncation示意图
  3. 闪回查询

闪回查询时选用指定时间点的Readview通过History list构建数据历史数据视图,返回查询结果。

参数说明

在管理控制台的参数修改页面,通过设置表1,可以开启闪回查询及设置闪回Readview和闪回查询的时间。

表1 参数说明

参数名称

参数类型

参数说明

innodb_rds_backquery_enable

Boolean

闪回查询功能的总开关。

  • true:开启闪回查询。
  • false:关闭闪回查询。

innodb_rds_backquery_readview_interval

INT

闪回Readview生成的时间间隔。单位:0.1秒。

默认值:10。取值范围:1-10。

该值越小,闪回查询相对越准确,但是用于存储Readview的系统表存储的数据越多,空间占用越大。

innodb_rds_backquery_window

INT

闪回查询支持最长留存时间。单位:秒。

默认值:3600。取值范围:60-604800。

此时间越长,Undo log占用的存储空间也将越多。

Innodb_rds_backquery_purge_mvcc_pct

DOUBLE

MVCC Purge占MVCC Purge和BACKQUERY Purge总次数的比例。单位:%。

默认值:50。取值范围:1-99。

Innodb_rds_backquery_undo_async_trunc

Boolean

开启闪回开关后,是否启用异步线程来删除Undo log。

  • true:开启Undo log异步删除。
  • false:关闭Undo log异步删除。

Innodb_rds_backquery_purge_batches_per_cycle

INT

单轮次Purge最多处理的页面数量。

默认值:300。取值范围:1-5000。

Innodb_rds_backquery_purge_interval

INT

闪回后台线程触发Purge的时间间隔。单位:毫秒。

默认值:5。取值范围1-50。

新增系统表

TaurusDB已默认新增用于存储闪回Readview的系统表如下,您无需对系统表执行操作,TaurusDB会默认对系统表进行数据插入及清理操作。

CREATE TABLE `__taurus_sys__`.`backquery` (
  `Snapshot_time` bigint unsigned NOT NULL,
  `Low_limit_id` bigint unsigned NOT NULL,
  `Up_limit_id` bigint unsigned NOT NULL,
  `Low_limit_no` bigint unsigned NOT NULL,
  `Trx_ids_count` bigint unsigned NOT NULL,
  `Trx_ids` mediumblob,
  PRIMARY KEY (`Snapshot_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin STATS_PERSISTENT=0 ROW_FORMAT=DYNAMIC COMMENT='Backquery system table.'

使用指导

  • 支持在创建InnoDB表时通过设置BACKQUERY选项,将表标记为闪回表,或者将已经存在的表标记为闪回表。

    BACKQUERY选项支持0,1,default。其中如果不指定BACKQUERY选项,表示非闪回表。

    • 0:表示非闪回表。
    • 1:表示闪回表。
    • default:表示非闪回表。

    例如:

    CREATE TABLE my_table(
        id INT AUTO_INCREMENT PRIMARY KEY,
        data VARCHAR(255)
    ) ENGINE=InnoDB, BACKQUERY=1;
  • 支持SELECT ... FROM <table name> AS OF TIMESTAMP <time>的闪回查询语法,通过time指定闪回查询的时间点,精确到0.1秒。

    例如:

    SELECT * FROM employee AS OF TIMESTAMP '2025-02-01 14:30:00.5'; 

    使用该SQL可以查询employee表在2025-02-01 14:30:00的第5个0.1秒时的数据。

    使用注意如下:

    • 如果时间没有填写完整。则自动将后续数值填写为0。
    • 当输入的时间不存在相应的Readview时,在“innodb_rds_backquery_window”参数设置的时间范围内自动找时间更早的readview。
  • 支持的复杂语句
    • Join语句
      SELECT Employees.name, Departments.name AS department FROM Employees 
        JOIN Departments AS OF TIMESTAMP @a ON Employees.departmentID = Departments.id;
    • Union语句
      SELECT * from EmployeesA UNION SELECT * FROM EmployeesB AS OF TIMESTAMP @a;
    • 子查询
      SELECT e.name AS employee_name,
        (SELECT d.department_name FROM Departments AS OF TIMESTAMP @a d
         WHERE d.id = e.departmentID) AS department_name
      FROM Employees e;

相关文档