---
title: OceanBase 闪回查询功能介绍-OceanBase数据库使用指南
description: 了解OceanBase数据库在实际应用中关于OceanBase 闪回查询功能介绍相关的常见问题和使用技巧，帮助您快速解决OceanBase 闪回查询功能介绍的难题。
image: https://mdn.alipayobjects.com/huamei_22khvb/afts/img/A*OSPzQ6GUQF4AAAAAQHAAAAgAeiGDAQ/original
---
切换语言

- 中文站 - 简体中文
- International - English
- 日本站 - 日本語

划线反馈

# OceanBase 闪回查询功能介绍

更新时间：2026-08-25 02:41

适用版本： V2.1.x 内容类型：TechNote  

## 总结说明

闪回查询（Flashback Query）允许用户查询某个历史版本的数据。在某些业务场景下，需要找回历史某个时间点的数据，可以使用闪回查询功能。在 OceanBase 数据库中有以下几种实现闪回查询的方法：

1. 通过 `undo_retention` 来控制多版本数据（MVCC）的保存时间，使用 `AS OF SCN` 和 `AS OF TIMESTAMP` 来查询历史版本的数据。
 2. 通过创建 restore point 来建立数据恢复的一致点。
 3. 通过合并的大版本号来查询当前 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 的闪回查询验证

```sql
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 的闪回查询验证

```sql
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 的闪回查询验证

```sql
-- 调小 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 的闪回查询验证

```sql
-- 调小 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]> 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` 的多冻结版本查询需要两个条件：

1. `max_kept_major_version_number` 用于设置数据保留的冻结版本数量，默认值为 2。
 2. `FROZEN_VERSION` Hint 指示服务器读取某个基线数据的版本。

使用 `FROZEN_VERSION` 的多冻结版本查询的注意事项：

- 执行 `FROZEN_VERSION` 查询后需要 commit/rollback 事务，否则会影响当前会话下该表的后续 DML 操作：

```plain
ERROR 1235 (0A000): different consistency type in one transaction not supported

```

参数 `max_kept_major_version_number` 用于设置数据保留的冻结版本数量：

| 属性 | 描述 |
| --- | --- |
| 参数类型 | 整型 |
| 默认值 | 2 |
| 取值范围 | [1, 16] |
| 是否重启 OBServer 生效 | 否 |

#### 测试验证

##### MySQL 租户基于 FROZEN_VERSION 的多版本查询验证

```sql
-- 查询当前数据
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 的多版本查询验证

```sql
-- 查询当前数据
obclient [SYS]> select * from t1;
+------+
| ID   |
+------+
|    1 |
|    2 |
|    3 |
|    4 |
+------+
4 rows in set (0.004 sec)

-- 插入数据
obclient [SYS]> insert into t1 values(5);
Query OK, 1 row affected (0.016 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。

Previous

[INSERT 报错 transaction needs rollback](https://www.oceanbase.com/knowledge-base/oceanbase-database-1000000000209955)

Next

[事务空闲超时，错误代码 ERROR 6002](https://www.oceanbase.com/knowledge-base/oceanbase-database-1000000000217852) ![有帮助](https://gw.alipayobjects.com/mdn/ob_asset/afts/img/A*y6ocSqN8cqsAAAAAAAAAAAAAARQnAQ)![无帮助](https://gw.alipayobjects.com/mdn/ob_asset/afts/img/A*BG9IQJyLHF8AAAAAAAAAAAAAARQnAQ)![反馈](https://gw.alipayobjects.com/mdn/ob_asset/afts/img/A*eTWdQKCRKHwAAAAAAAAAAAAAARQnAQ)[AI](https://www.oceanbase.com/obi) 咨询热线
