
# 闪回恢复
闪回恢复功能是数据库恢复技术的一环，可以有选择性地撤销一个已提交的事务，将数据从人为不正确的操作中进行恢复。按照恢复对象与底层机制的不同，GaussDB闪回恢复主要分为：闪回查询、闪回表、闪回DROP/TRUNCATE和闪回库。
在采用闪回技术之前，只能通过备份恢复、PITR等手段找回已提交的数据库修改，恢复时长需要数分钟甚至数小时。采用闪回技术后，其中通过闪回DROP/TRUNCATE恢复已提交的事务，只需要秒级，并且恢复时间和数据库大小无关。
![](https://support.huaweicloud.com/distributed-devg-v10-gaussdb/public_sys-resources/note_3.0-zh-cn.png)
- Ustore存储引擎支持闪回查询、闪回表、闪回DROP/TRUNCATE和闪回库；Astore存储引擎只支持闪回DROP/TRUNCATE功能。
- 备机不支持闪回操作。
- 用户可以根据需要开启闪回功能，开启后会带来一定的性能劣化。
 
#### 为什么需要闪回恢复
在数据库的日常运维与开发过程中，人为误操作是难以完全避免的风险，例如误删一张表、误执行TRUNCATE清空数据，或在业务逻辑变更中错误地更新了关键记录。这类逻辑损坏通常只影响一张或一组表，而非整个数据库实例。
闪回恢复的核心价值在于：当上述逻辑损坏发生时，无需对整个实例做备份恢复或PITR（时间点恢复）重建，即可针对受损的表、库等对象进行快速、局部的还原，从而显著降低人为误操作带来的业务中断风险。
#### 闪回恢复的优势是什么
- **秒级恢复：**通过闪回DROP/TRUNCATE恢复已提交的删除、清空数据只需秒级，恢复时间与数据库大小无关，相比备份恢复和PITR大幅缩短了恢复窗口。
- **局部精准恢复：**当逻辑损坏仅限于一张或一组表时，可单独将受损对象恢复至特定时间点，无需对整个实例进行回退，避免影响其他正常业务数据。
- **多种恢复粒度：**提供闪回查询、闪回表、闪回DROP/TRUNCATE以及闪回库等多种能力，覆盖从"查看历史数据"到"恢复被删除对象"的不同恢复需求。
- **时间点与CSN双重定位：**既支持以时间戳（TIMESTAMP）方式指定闪回点，也支持以CSN（Commit Sequence Number，提交序列号）方式精确定位一致性点，满足不同精度的恢复要求。
 
#### 闪回恢复的使用场景
- **误删表/误清空** **后的快速找回：**开发或运维人员在变更过程中误执行了DROP或TRUNCATE操作，导致业务表数据丢失。在已开启回收站（recyclebin）的前提下，可使用闪回DROP或闪回TRUNCATE从回收站还原被删除的表及其索引、约束等附属结构，秒级恢复业务。
- **误更新数据的逻辑重建：**业务团队在批量更新或脚本执行中错误地修改了关键记录，但损坏范围仅限于个别表。在undo_retention_time已保留相应时间范围Undo旧版本的前提下，可先通过闪回查询查看该表在出错前某一时间点的快照数据，确认正确版本后，再使用闪回表将整张表恢复至该时间点，实现表级数据还原而不影响其他对象。
- **历史数据审计与比对：**数据分析或审计人员需要查看某张表在过去某个时间点的状态以核对数据变化。在undo_retention_time已保留相应历史版本的前提下，借助闪回查询可直接读取指定TIMESTAMP或CSN下的历史版本，无需额外搭建历史库，即可完成数据的回溯查看与逻辑重建。
 
#### 闪回恢复的工作原理
从整体上看，GaussDB闪回恢复依托两大底层机制实现：一是Ustore存储引擎的Undo多版本机制，二是回收站机制。前者负责保留行数据的历史版本，支撑闪回查询与闪回表；后者负责保存被删除对象的物理文件，支撑闪回DROP、闪回TRUNCATE与闪回库。
基于Undo的闪回（闪回查询、闪回表）依赖MVCC多版本并发控制。Ustore在更新或删除数据时，会通过Undo子系统将旧版本单独保存，并由GUC参数undo_retention_time控制旧版本的保留时长。执行闪回查询时，系统根据指定的时间点或CSN检索对应的旧版本数据并返回；执行闪回表时，系统在此基础上删除该时间点之后产生的增量数据，并找回该区间内被删除的数据，从而将整张表还原到指定时间点。
基于回收站的闪回（闪回DROP、闪回TRUNCATE、闪回库）依赖回收站机制。开启回收站后，执行表或索引删除时，系统会在原对象所在SCHEMA中自动生成以"BIN"开头的隐藏对象，记录被删除对象的物理文件位置；闪回时再依据这些记录还原物理文件，实现已DROP或TRUNCATE对象的恢复。回收站对象的保留时长由recyclebin_retention_time（表级）等参数控制，超时后自动清理。其中，闪回库依赖独立的库级回收站（gs_db_recyclebin），由enable_db_recyclebin、dbrecyclebin_retention_time等参数控制。
通过Undo与回收站两套机制的协同，闪回恢复既能读取与还原行级历史版本，又能找回被整体删除的对象。
#### 闪回恢复的分类
按照恢复对象与底层机制的不同，GaussDB闪回恢复主要分为以下几类：
- **闪回查询**
  - **简介**
    查询过去某个时间点表的快照数据，用于查看和逻辑重建被意外删除或更改的受损数据。基于MVCC多版本机制，通过检索旧版本获取指定历史版本数据。
    
  
  - **前提条件**
    需要设置GUC参数undo_retention_time，该参数的值表示旧版本undo的保留时间。
    
  
  - **示例**
    ```
    --前置操作建表和插入数据。
    gaussdb=# CREATE TABLE tb_t1 (c1 int, c2 int) WITH(storage_type = ustore);
    gaussdb=# INSERT INTO tb_t1 values (1,1),(2,2);
    --查询当前时间和CSN。
    gaussdb=# SELECT now(), int8in(xidout(next_csn)) FROM gs_get_next_xid_csn() limit 1;
                  now              | int8in  
    -------------------------------+---------
     2025-04-22 15:22:47.574995+08 | 2020912
    (1 row)
    --模拟数据误操作。
    gaussdb=# UPDATE tb_t1 SET C1=222,C2=222 WHERE C1 = 2;
    gaussdb=# SELECT * FROM tb_t1;
     c1  | c2  
    -----+-----
       1 |   1
     222 | 222
    (2 rows)
    --根据时间查询该表修改之前的数据。
    gaussdb=# SELECT * FROM tb_t1 TIMECAPSULE TIMESTAMP '2025-04-22 15:22:47.574995';
     c1 | c2 
    ----+----
      1 |  1
      2 |  2
    (2 rows)
    --根据CSN查询该表修改之前的数据。
    gaussdb=# SELECT * FROM tb_t1 TIMECAPSULE CSN '2020912';
     c1 | c2 
    ----+----
      1 |  1
      2 |  2
    (2 rows)
    --删除。
    gaussdb=# DROP TABLE tb_t1;
    ```
    
   
- **闪回表**
  - **简介**
    闪回表可以将表恢复至特定时间点或CSN点。当逻辑损坏仅限于一个或一组表、而非整个数据库时，可借助该特性（基于MVCC多版本机制）快速实现表级数据还原。
    
  
  - **前提条件**
    需要设置GUC参数undo_retention_time，该参数的值表示旧版本undo的保留时间。
    
  
  - **示例**
    ```
    --前置操作建表和插入数据。
    gaussdb=# CREATE TABLE tb_t2 (c1 int, c2 int) WITH(storage_type = ustore);
    gaussdb=# INSERT INTO tb_t2 VALUES (1,1),(2,2);
    --查询当前时间和CSN。
    gaussdb=# SELECT now(), int8in(xidout(next_csn)) FROM gs_get_next_xid_csn() limit 1;
                 now              | int8in  
    ------------------------------+---------
     2025-04-22 15:32:22.99132+08 | 2021175
    (1 row)
    --模拟数据误操作。
    gaussdb=# UPDATE tb_t2 SET c1 = 222, c2 = 222 WHERE C1 = 2;
    gaussdb=# SELECT * FROM tb_t2;
     c1  | c2  
    -----+-----
       1 |   1
     222 | 222
    (2 rows)
    --将表闪回至误操作之前时间点。
    gaussdb=# TIMECAPSULE table tb_t2 TO TIMESTAMP to_timestamp('2025-04-22 15:32:22.99132','YYYY-MM-DD HH24:MI:SS.FF');
    gaussdb=# SELECT * FROM tb_t2;
     c1 | c2 
    ----+----
      1 |  1
      2 |  2
    (2 rows)
    --也可以使用如下SQL,根据CSN闪回该表。
    gaussdb=# UPDATE tb_t2 SET c1 = 333, c2 = 333 where c1 = 2;
    gaussdb=# TIMECAPSULE table tb_t2 TO CSN 2021175;
    gaussdb=# SELECT * FROM tb_t2;
     c1 | c2 
    ----+----
      1 |  1
      2 |  2
    (2 rows)
    --删除。
    gaussdb=# DROP TABLE tb_t2;
    ```
    
   
- **闪回DROP/TRUNCATE**
  - **简介**
    - 闪回DROP：可以恢复意外删除的表，从回收站中恢复被删除的表及其附属结构，如索引、表约束等。闪回DROP是基于回收站机制，通过还原回收站中记录的表的物理文件，实现已DROP表的恢复。
    
    - 闪回TRUNCATE：可以恢复误操作或意外被TRUNCATE的表，从回收站中恢复被TRUNCATE的表及索引的物理数据。闪回TRUNCATE基于回收站机制，通过还原回收站中记录的表的物理文件，实现已TRUNCATE表的恢复。
     
  
  - **前提条件**
    - 设置GUC参数enable_recyclebin的值为on，启用回收站功能。
    
    - 设置GUC参数recyclebin_retention_time，该参数的值为回收站保留对象的时间，超时的对象回收站会自动清理。
     
  
  - **示例**
    ```
    --前置操作建表和插入数据。
    gaussdb=# CREATE TABLE tb_t3 (c1 int,c2 int) WITH(storage_type = ustore);
    gaussdb=# INSERT INTO tb_t3 VALUES (1,1), (2,2);
    --删除该表。
    gaussdb=# DROP TABLE tb_t3;
    --闪回至删除之前。
    gaussdb=# TIMECAPSULE TABLE tb_t3 TO BEFORE DROP;
    gaussdb=# SELECT * FROM tb_t3;
     c1 | c2 
    ----+----
      1 |  1
      2 |  2
    (2 rows)
    --使用TRUNCATE清空该表。
    gaussdb=# TRUNCATE TABLE tb_t3;
    --闪回至清空之前。
    gaussdb=# TIMECAPSULE TABLE tb_t3 TO BEFORE TRUNCATE;
    gaussdb=# SELECT * FROM tb_t3;
     c1 | c2 
    ----+----
      1 |  1
      2 |  2
    (2 rows)
    --删除。
    DROP TABLE tb_t3;
    ```
    
   
- **闪回库**
  - **简介：**
    恢复意外删除的库，从库级回收站中恢复被删除的库及其关联对象。闪回库基于回收站机制，通过还原回收站中记录的库的物理文件，实现已DROP库的恢复。
    
  
  - **前提条件**
    - 开启enable_db_recyclebin参数，启用回收站。
    
    - dbrecyclebin_retention_time参数用于设置回收站对象的保留时间，超过该时间的回收站对象将被自动清理。
    
    - dbrecyclebin_maxsize参数用于设置回收站容量，超过容量将不能放入回收站。
     
  
  - **示例**
    开启库级回收站后，闪回回收站中的数据库。
    ```
    --查看回收站。
    gaussdb=# SELECT * FROM gs_db_recyclebin;
     rcydbid | rcyname | rcyoriginname | rcyrecyclecsn | rcyrecycletime | rcytablespaces | rcydbsize 
    ---------+---------+---------------+---------------+----------------+----------------+-----------
    (0 rows)
    --创建数据库。
    gaussdb=# CREATE DATABASE flashback_db;
    CREATE DATABASE
    --删除数据库放入回收站。
    gaussdb=# DROP DATABASE flashback_db;
    DROP DATABASE
    gaussdb=# SELECT * FROM gs_db_recyclebin;
     rcydbid |          rcyname          | rcyoriginname | rcyrecyclecsn |        rcyrecycletime        | rcytablespaces | rcydbsize 
    ---------+---------------------------+---------------+---------------+------------------------------+----------------+-----------
       82523 | BIN$1425B67F$2F7B1738==$0 | flashback_db  |         13916 | 2024-12-11 09:02:35.20606-05 | 1663           |     26272
    (1 row)
    --可通过回收站名闪回drop后的数据库。
    gaussdb=# TIMECAPSULE DATABASE "BIN$1425B67F$2F7B1738==$0" to before drop;
    TimeCapsule Database
    --可通过原名闪回drop后的数据库。
    gaussdb=# TIMECAPSULE DATABASE flashback_db to before drop;
    TimeCapsule Database
    --可通过回收站名闪回后重命名。
    gaussdb=# TIMECAPSULE DATABASE "BIN$1425B67F$2F7B1738==$0" to before drop rename to flashback_db1;
    TimeCapsule Database
    --可通过原名闪回后重命名。
    gaussdb=# TIMECAPSULE DATABASE flashback_db to before drop rename to flashback_db1;
    TimeCapsule Database
    gaussdb=# SELECT * FROM gs_db_recyclebin;
     rcydbid | rcyname | rcyoriginname | rcyrecyclecsn | rcyrecycletime | rcytablespaces | rcydbsize 
    ---------+---------+---------------+---------------+----------------+----------------+-----------
    (0 rows)
    --查看闪回后的库。
    gaussdb=# SELECT * FROM pg_database where datname = 'flashback_db';
       datname    | datdba | encoding | datcollate  |  datctype   | datistemplate | datallowconn | datconnlimit | datlastsysoid | datfrozenxid | dattablespace 
    | datcompatibility | datacl | datfrozenxid64 | datminmxid | dattimezone | dattype 
    --------------+--------+----------+-------------+-------------+---------------+--------------+--------------+---------------+--------------+---------------
    +------------------+--------+----------------+------------+-------------+---------
     flashback_db |     10 |        7 | en_US.UTF-8 | en_US.UTF-8 | f             | t            |           -1 |         12995 | 0            |          1663 
    | A                |        |          40936 |          2 | PRC         | D
    (1 row)
    ```
    
   
 
#### 闪回恢复与备份恢复的区别
闪回恢复与备份恢复都是GaussDB的数据恢复手段，二者的共同点在于：都用于在数据发生丢失或损坏后，将数据恢复到出错前的状态，以保障数据的安全可靠。
二者的核心差异在于数据来源与恢复方式：闪回基于运行实例内部保留的Undo历史版本与回收站数据，无需借助外部数据即可在线恢复；而备份恢复基于独立保存的物理备份集（全量备份与增量备份）以及归档WAL日志（用于PITR），需要重新加载备份并回放日志来重建数据。这一差异主要源于数据来源不同------闪回依赖的是在线保留、有保留时间限制的历史版本与回收站对象，备份恢复依赖的是离线保存的完整备份与日志。
由于上述差异，二者在恢复粒度、速度与适用范围上各有侧重：闪回可对表、库等对象进行局部恢复，恢复速度快------其中闪回DROP/TRUNCATE可达秒级且与数据库大小无关，但只能恢复到Undo或回收站保留期之内；备份恢复通常以整个实例或数据库为单位进行重建，恢复时长随数据量增长可达数分钟甚至数小时，但能够恢复到更早的历史时间点，并可应对介质损坏、实例级灾难等闪回无法覆盖的场景。因此，闪回更适合保留期内人为误操作的快速恢复，备份恢复更适合超出保留期、整库灾难或介质故障的恢复场景，二者互为补充。
| **对比维度** | **闪回恢复**                       | **备份恢复**                |
|:---|:---|:---|
| 共同点      | 均为数据恢复手段，都用于将数据恢复到出错前的状态。                               ||
| 数据来源     | 实例内Undo历史版本与回收站。               | 独立的物理备份集与归档WAL日志（PITR）。 |
| 恢复粒度     | 表级/库级等局部对象。                    | 整个实例或数据库。               |
| 恢复速度     | 较快；闪回DROP/TRUNCATE可达秒级、与库大小无关。 | 数分钟至数小时，与数据量相关。         |
| 时间范围     | 限于Undo/回收站保留期内。                | 可恢复到更早的历史时间点。           |
| 典型场景     | 保留期内人为误操作恢复。                   | 介质损坏、实例级灾难、超保留期恢复。      |
   
#### 与闪回恢复相关的特性和操作
在了解闪回恢复的核心概念与适用场景后，如需了解更多详情以及在实际业务中配置使用，可参考以下对应章节：
- 前置开关与参数配置：
  - 开启闪回功能：闪回查询/闪回表依赖Undo旧版本保留，需配置undo_retention_time；关闭（设为0）时无法使用闪回功能。详情参考《参考》中"数据库运行参数说明 \> GUC参数说明 \> 闪回相关参数"章节。
  
  - 开启回收站：闪回DROP/TRUNCATE需将enable_recyclebin设置为on，闪回库需将enable_db_recyclebin设置为on，并可通过recyclebin_retention_time、dbrecyclebin_retention_time设置回收站对象的保留时长。详情参考《参考》中"数据库运行参数说明 \> GUC参数说明 \> 闪回相关参数"章节。
   
- 闪回恢复操作：
  - 闪回查询：使用"TIMECAPSULE { TIMESTAMP \| CSN } expression"查询表在指定时间点或CSN点的历史数据，详情请参考[闪回查询](https://support.huaweicloud.com/distributed-devg-v10-gaussdb/gaussdb-12-0555.html)章节。
  
  - 闪回表：使用"TIMECAPSULE TABLE table_name TO { TIMESTAMP \| CSN } expression"将表恢复至指定时间点，详情请参考[闪回表](https://support.huaweicloud.com/distributed-devg-v10-gaussdb/gaussdb-12-0556.html)章节
  
  - 闪回DROP/TRUNCATE：从回收站恢复被删除或被清空的表及其附属结构，详情请参考[闪回DROP/TRUNCATE](https://support.huaweicloud.com/distributed-devg-v10-gaussdb/gaussdb-12-0557.html)章节
   
 
