基于湖库一体架构,统一管理结构化、半结构化与非结构化等多模态数据,一个系统承载事务处理、实时分析与 AI 工作负载。
OceanBase 闪回查询功能介绍
更新时间:2026-08-25 02:41
总结说明
闪回查询(Flashback Query)允许用户查询某个历史版本的数据。在某些业务场景下,需要找回历史某个时间点的数据,可以使用闪回查询功能。在 OceanBase 数据库中有以下几种实现闪回查询的方法:
- 通过
undo_retention来控制多版本数据(MVCC)的保存时间,使用AS OF SCN和AS OF TIMESTAMP来查询历史版本的数据。 - 通过创建 restore point 来建立数据恢复的一致点。
- 通过合并的大版本号来查询当前 SSTable 保留的大版本数据。
详细说明
基于 undo_retention 的闪回查询
参数 undo_retention 用于设置系统应保留的多版本数据范围,单位为秒,在转储时控制多版本数据的回收。
| 属性 | 描述 |
|---|---|
| 参数类型 | 整型 |
| 默认值 | 1800 |
| 取值范围 | [0, 4294967295] |
| 是否重启 OBServer 节点生效 | 否 |
OceanBase 数据库 MVCC 机制的数据会保留多个版本的历史数据行,您可以通过 undo_retention 来控制转储中保留的多版本数据范围。其中:
- Oracle 模式:
AS OF SCN和AS OF TIMESTAMP。 - MySQL 模式:
AS OF SNAPSHOT。 - 当
undo_retention的值为 0 时,表示未开启多版本转储,即转储文件仅保留当前最新版本的行数据。 - 当
undo_retention的值大于 0 时,表示开启多版本转储,并且转储文件保留这段时间(单位为秒)以内的多版本行数据。假如undo_retention=t,当前时间为 T,则系统会自动保留 [T-t ~ T] 时间范围内的任意多版本数据,具体场景如下:- 若 [T-t ~ T] 范围未发生转储,memstore 中最少会保留 [T-t ~ T] 范围的多版本数据。
- 若 T0 时发生转储,则 [T0-t ~ T0] 范围的多版本数据会保留在 sstable。
- 转储后,闪回查询可以访问 [T0-t ~ T0] 范围的历史数据,也可以访问 [T-t ~ T] 范围的历史数据,但不一定能访问 [T0 ~ T-t] 范围的历史数据,因为 memstore 中过多的多版本数据会被回收。
注意:租户开启多版本转储后,大版本合并会保留对应的增量转储文件,但 Major SSTable 中不会存放多版本数据。
测试验证
MySQL 租户基于 undo_retention 的闪回查询验证
obclient [test]> select count(*) from t1;
+----------+
| count(*) |
+----------+
| 0 |
+----------+
1 row in set (0.034 sec)
obclient [test]> select time_to_usec(now());
+---------------------+
| time_to_usec(now()) |
+---------------------+
| 1687160132000000 |
+---------------------+
1 row in set (0.002 sec)
obclient [test]> insert into t1 values(1,'aa');
Query OK, 1 row affected (0.068 sec)
obclient [test]> select count(*) from t1;
+----------+
| count(*) |
+----------+
| 1 |
+----------+
1 row in set (0.001 sec)
obclient [test]> select count(*) from t1 as of snapshot 1687160132000000;
+----------+
| count(*) |
+----------+
| 0 |
+----------+
1 row in set (0.004 sec)
Oracle 租户基于 undo_retention 的闪回查询验证
obclient [OBORACLE]> select * from t1;
+------+------+
| ID | NAME |
+------+------+
| 1 | aaa |
+------+------+
1 row in set (0.001 sec)
obclient [OBORACLE]> SELECT (sysdate - to_date('1970-01-01 08:00:00', 'yyyy-mm-dd hh24:mi:ss')) * 86400 * 1000 * 1000 AS timestamp_to_scn FROM DUAL;
+------------------+
| TIMESTAMP_TO_SCN |
+------------------+
| 1687161144000000 |
+------------------+
1 row in set (0.003 sec)
obclient [OBORACLE]> insert into t1 values(2,'bbb');
Query OK, 1 row affected (0.002 sec)
obclient [OBORACLE]> commit;
Query OK, 0 rows affected (0.007 sec)
obclient [OBORACLE]> select * from t1;
+------+------+
| ID | NAME |
+------+------+
| 1 | aaa |
| 2 | bbb |
+------+------+
2 rows in set (0.001 sec)
obclient [OBORACLE]> select * from t1 as of scn 1687161144000000;
+------+------+
| ID | NAME |
+------+------+
| 1 | aaa |
+------+------+
1 row in set (0.005 sec)
obclient [OBORACLE]> select * from t1 as of timestamp to_timestamp('2023-06-19 15:52:24','yyyy-mm-dd HH24:MI:SS');
+------+------+
| ID | NAME |
+------+------+
| 1 | aaa |
+------+------+
1 row in set (0.002 sec)
基于 restore point 的闪回查询
在很多应用系统中,用户需要查询数据库中的某个时间点,或者特定版本的数据来完成一些数据分析或汇总之类的操作。OceanBase 数据库在 V2.2.7x 版本中提供了 Restore Point 功能,允许用户在租户上创建 Restore Point,将历史版本的数据保存下来。Restore Point 功能类似于租户的快照点,您可以通过闪回查询的方式来访问特定版本的历史数据。
由于 Restore Point 功能依赖 GTS 维护全局的一致性快照,故在使用 Restore Point 时,需要开启 GTS。
通过 CREATE RESTORE POINT 语句创建租户级的 Restore Point。创建 Restore Point 后,可以通过查询 V$RESTORE_POINT 视图来查看当前可用的 Restore Point,并根据查询到的 Restore Point 进行数据分析。
测试验证
MySQL 租户基于 restore point 的闪回查询验证
-- 调小 undo_retention 避免受 undo_retention 干扰
obclient [obmysql]> show variables like '%undo%';
+----------------+-------+
| Variable_name | Value |
+----------------+-------+
| undo_retention | 60 |
+----------------+-------+
1 row in set (0.006 sec)
-- 创建表插入数据
obclient [obmysql]> create table t1(id int);
Query OK, 0 rows affected (0.226 sec)
obclient [obmysql]> insert into t1 values(1);
Query OK, 1 row affected (0.059 sec)
obclient [obmysql]> commit;
Query OK, 0 rows affected (0.002 sec)
obclient [obmysql]> select * from t1;
+------+
| id |
+------+
| 1 |
+------+
1 row in set (0.009 sec)
-- 创建闪回点
obclient [obmysql]> CREATE RESTORE POINT restore_point;
Query OK, 0 rows affected (0.031 sec)
obclient [obmysql]> SELECT * FROM oceanbase.V$RESTORE_POINT;
+-----------+------------------+----------------------------+---------------+
| TENANT_ID | SNAPSHOT | TIME | NAME |
+-----------+------------------+----------------------------+---------------+
| 1004 | 1687274705342087 | 2023-06-20 23:25:05.345229 | restore_point |
+-----------+------------------+----------------------------+---------------+
1 row in set (0.061 sec)
-- 对表进行 DML 操作
obclient [obmysql]> insert into t1 values(2);
Query OK, 1 row affected (0.006 sec)
obclient [obmysql]> commit;
Query OK, 0 rows affected (0.001 sec)
obclient [obmysql]> select * from t1;
+------+
| id |
+------+
| 1 |
| 2 |
+------+
2 rows in set (0.002 sec)
-- 查询闪回点数据及闪回点之后的数据可以查询,并且不受 undo_retention 影响
obclient [obmysql]> select * from t1 as of snapshot 1687274705342087;
+------+
| id |
+------+
| 1 |
+------+
1 row in set (0.002 sec)
obclient [obmysql]> select * from t1 as of snapshot 1687274705342088;
+------+
| id |
+------+
| 1 |
+------+
1 row in set (0.007 sec)
-- 查询闪回点之前数据无法查询,提示无效 timestamp
obclient [obmysql]> select * from t1 as of snapshot 1687274705342086;
ERROR 4344 (HY000): invalid timestamp
Oracle 租户基于 restore point 的闪回查询验证
-- 调小 undo_retention 避免受 undo_retention 干扰
obclient [SYS]> show variables like 'undo_retention';
+----------------+-------+
| VARIABLE_NAME | VALUE |
+----------------+-------+
| undo_retention | 60 |
+----------------+-------+
1 row in set (0.003 sec)
-- 创建表插入数据
obclient [SYS]> create table t1(id int);
Query OK, 0 rows affected (0.117 sec)
obclient [SYS]> insert into t1 values(1);
Query OK, 1 row affected (0.061 sec)
obclient [SYS]> commit;
Query OK, 0 rows affected (0.005 sec)
obclient [SYS]> select * from t1;
+------+
| ID |
+------+
| 1 |
+------+
1 row in set (0.013 sec)
-- 创建闪回点
obclient [SYS]> CREATE RESTORE POINT restore_point;
Query OK, 0 rows affected (0.018 sec)
obclient [SYS]> SELECT * FROM V$RESTORE_POINT;
+-----------+------------------+------------------------------+---------------+
| TENANT_ID | SNAPSHOT | TIME | NAME |
+-----------+------------------+------------------------------+---------------+
| 1002 | 1687274711073594 | 20-JUN-23 11.25.11.075086 PM | RESTORE_POINT |
+-----------+------------------+------------------------------+---------------+
1 row in set (0.012 sec)
-- 对表进行 DML 操作
obclient [SYS]> insert into t1 values(2);
Query OK, 1 row affected (0.001 sec)
obclient [SYS]> commit;
Query OK, 0 rows affected (0.005 sec)
obclient [SYS]> select * from t1;
+------+
| ID |
+------+
| 1 |
| 2 |
+------+
2 rows in set (0.002 sec)
-- 查询闪回点数据及闪回点之后的数据可以查询,并且不受 undo_retention 影响
obclient [SYS]> select * from t1 as of scn 1687274711073594;
+------+
| ID |
+------+
| 1 |
+------+
1 row in set (0.006 sec)
obclient [SYS]> select * from t1 as of scn 1687274711073595;
+------+
| ID |
+------+
| 1 |
+------+
1 row in set (0.002 sec)
-- 查询闪回点之前数据无法查询,提示无效 timestamp
obclient [SYS]> select * from t1 as of scn 1687274711073593;
ORA-08186: invalid timestamp
基于 FROZEN_VERSION 的多版本查询
使用 FROZEN_VERSION 的多冻结版本查询需要两个条件:
max_kept_major_version_number用于设置数据保留的冻结版本数量,默认值为 2。FROZEN_VERSIONHint 指示服务器读取某个基线数据的版本。
使用 FROZEN_VERSION 的多冻结版本查询的注意事项:
- 执行
FROZEN_VERSION查询后需要 commit/rollback 事务,否则会影响当前会话下该表的后续 DML 操作:
ERROR 1235 (0A000): different consistency type in one transaction not supported
参数 max_kept_major_version_number 用于设置数据保留的冻结版本数量:
| 属性 | 描述 |
|---|---|
| 参数类型 | 整型 |
| 默认值 | 2 |
| 取值范围 | [1, 16] |
| 是否重启 OBServer 生效 | 否 |
测试验证
MySQL 租户基于 FROZEN_VERSION 的多版本查询验证
-- 查询当前数据
obclient [obmysql]> select * from t1;
+------+
| id |
+------+
| 1 |
| 2 |
| 3 |
+------+
3 rows in set (0.004 sec)
-- 执行合并查看合并版本
obclient [oceanbase]> alter system major freeze;
Query OK, 0 rows affected (0.036 sec)
obclient [oceanbase]> select zone,name,value,info from __all_zone where name in ('frozen_version','merge_status');
+-------+----------------+-------+---------+
| zone | name | value | info |
+-------+----------------+-------+---------+
| | frozen_version | 10 | |
| | merge_status | 1 | MERGING |
| zone1 | merge_status | 1 | MERGING |
| zone2 | merge_status | 1 | MERGING |
| zone3 | merge_status | 1 | MERGING |
+-------+----------------+-------+---------+
5 rows in set (0.010 sec)
obclient [oceanbase]> select zone,name,value,info from __all_zone where name in ('frozen_version','merge_status');
+-------+----------------+-------+------+
| zone | name | value | info |
+-------+----------------+-------+------+
| | frozen_version | 10 | |
| | merge_status | 0 | IDLE |
| zone1 | merge_status | 0 | IDLE |
| zone2 | merge_status | 0 | IDLE |
| zone3 | merge_status | 0 | IDLE |
+-------+----------------+-------+------+
-- 插入数据
obclient [obmysql]> insert into t1 values(4);
Query OK, 1 row affected (0.021 sec)
obclient [obmysql]> select * from t1;
+------+
| id |
+------+
| 1 |
| 2 |
| 3 |
| 4 |
+------+
4 rows in set (0.003 sec)
-- 合并版本查询
obclient [obmysql]> SELECT /*+ FROZEN_VERSION(10) */ * from t1;
+------+
| id |
+------+
| 1 |
| 2 |
| 3 |
+------+
3 rows in set (0.002 sec)
-- MySQL 租户模式默认是 autocommit,因此合并版本查询不需要手动 commit 或者 rollback,不影响 DML。
-- 关闭 autocommit 后,合并版本查询需要 commit 或者 rollback,否则 DML 会报错。
obclient [obmysql]> insert into t1 values(5);
Query OK, 1 row affected (0.006 sec)
obclient [obmysql]> set autocommit=off;
Query OK, 0 rows affected (0.002 sec)
obclient [obmysql]> SELECT /*+ FROZEN_VERSION(10) */ * from t1;
+------+
| id |
+------+
| 1 |
| 2 |
| 3 |
+------+
3 rows in set (0.002 sec)
obclient [obmysql]> insert into t1 values(6);
ERROR 1235 (0A000): different consistency type in one transaction not supported
Oracle 租户基于 FROZEN_VERSION 的多版本查询验证
-- 查询当前数据
obclient [SYS]> select * from t1;
+------+
| ID |
+------+
| 1 |
| 2 |
| 3 |
| 4 |
+------+
4 rows in set (0.004 sec)
-- 执行合并查看合并版本
obclient [oceanbase]> alter system major freeze;
Query OK, 0 rows affected (0.036 sec)
obclient [oceanbase]> select zone,name,value,info from __all_zone where name in ('frozen_version','merge_status');
+-------+----------------+-------+---------+
| zone | name | value | info |
+-------+----------------+-------+---------+
| | frozen_version | 10 | |
| | merge_status | 1 | MERGING |
| zone1 | merge_status | 1 | MERGING |
| zone2 | merge_status | 1 | MERGING |
| zone3 | merge_status | 1 | MERGING |
+-------+----------------+-------+---------+
5 rows in set (0.010 sec)
obclient [oceanbase]> select zone,name,value,info from __all_zone where name in ('frozen_version','merge_status');
+-------+----------------+-------+------+
| zone | name | value | info |
+-------+----------------+-------+------+
| | frozen_version | 10 | |
| | merge_status | 0 | IDLE |
| zone1 | merge_status | 0 | IDLE |
| zone2 | merge_status | 0 | IDLE |
| zone3 | merge_status | 0 | IDLE |
+-------+----------------+-------+------+
-- 插入数据
obclient [SYS]> insert into t1 values(5);
Query OK, 1 row affected (0.016 sec)
obclient [SYS]> commit;
Query OK, 0 rows affected (0.005 sec)
obclient [SYS]> select * from t1;
+------+
| ID |
+------+
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
+------+
5 rows in set (0.004 sec)
-- 合并版本查询
obclient [SYS]> SELECT /*+ FROZEN_VERSION(10) */ * from t1;
+------+
| ID |
+------+
| 1 |
| 2 |
| 3 |
| 4 |
+------+
4 rows in set (0.010 sec)
-- 执行了合并版本查询,需要 commit 或者 rollback 否则 DML 会报错
obclient [SYS]> insert into t1 values(6);
ORA-00600: internal error code, arguments: -4007, different consistency type in one transaction not supported
适用版本
OceanBase 2.x、3.x。