Oracle 19c RECOVER TABLE 恢复误删除数据

Oracle 19c RMAN 单表恢复(RECOVER TABLE)

1 概述

Oracle 19c 支持使用 RMAN 备份直接进行单表/单分区恢复,可恢复被删除(Drop)或截断的表数据。

这种恢复方式相当于 "傻瓜版",将原本需要手动执行的复杂操作集合起来自动完成。

可以从 RMAN 备份中将一个特定的表或分区恢复到某个时间点、SCN 或归档序列号,并且可以:

  • 使用 REMAP 选项将表恢复为一个新表或者分区中,也可以恢复到其他用户中
  • 使用 NOTABLEIMPORT 只生成 expdp 格式的 dump 文件,后续再进行恢复

2 RMAN 内部执行步骤

RECOVER TABLE 本质是自动化执行 TSPITR(表空间时间点恢复),RMAN 会自动执行以下 8 个步骤:

步骤 说明
1. 判断备份 判断哪些备份包含需要恢复的表或表分区
2. 检查空间 判断主机是否有足够空间创建 auxiliary instance
3. 创建辅助实例 创建 auxiliary database 并恢复表到辅助实例
4. 导出 dump 在辅助实例中使用 DataPump 导出表数据
5.(可选)导入 将 dump 文件导入到目标实例
6.(可选)重命名 在目标数据库中重命名恢复的表或分区
7. 清理 自动关闭并删除辅助实例
8. 清理文件 清理所有临时文件

内部流程详解

复制代码
1. 判断备份
   ↓
   判断哪些备份包含需要恢复的表或表分区
   根据指定的时间点确定可用的备份集
   
2. 检查空间
   ↓
   判断目标主机是否有足够空间创建 auxiliary instance
   空间不足则报错并退出
   
3. 创建辅助实例
   ↓
   根据源库参数文件(1:1 clone)创建辅助实例
   SID 由系统自动生成(如 wtrc)
   还原控制文件和数据文件
   应用归档日志到指定时间点
   
4. 打开辅助实例(只读)
   ↓
   以 RESETLOGS 方式打开辅助实例
   此时可以查询误删表的数据
   
5. DataPump 导出
   ↓
   在辅助实例中执行 expdp 导出误删表
   生成 dump 文件到 AUXILIARY DESTINATION
   
6. (可选)DataPump 导入
   ↓
   在生产库中执行 impdp 导入数据
   自动创建表并插入数据
   
7. (可选)重命名
   ↓
   如果使用 REMAP,重命名表
   
8. 清理
   ↓
   自动关闭并删除辅助实例
   清理所有临时文件和目录

⚠️ 注意:由于步骤 3 需要创建辅助实例(1:1 clone 源库参数),对主机物理资源要求很高,资源不足会执行失败。

3 语法

2.1 非PDB模式(CDB)

sql 复制代码
RECOVER TABLE schema.table_name
UNTIL TIME "to_date('2026-04-13 16:38:00','yyyy-mm-dd hh24:mi:ss')"
AUXILIARY DESTINATION '/backup/tablerecovery';

2.2 PDB模式

sql 复制代码
RECOVER TABLE schema.table_name OF PLUGGABLE DATABASE pdb_name
UNTIL TIME "to_date('2026-04-13 16:38:00','yyyy-mm-dd hh24:mi:ss')"
AUXILIARY DESTINATION '/backup/tablerecovery';

2.3 常用参数

参数 说明
OF PLUGGABLE DATABASE 指定PDB名称(PDB模式必选)
UNTIL TIME 恢复到指定时间点
UNTIL SCN 恢复到指定SCN
UNTIL LOGSEQ 恢复到指定日志序列号
AUXILIARY DESTINATION 辅助实例数据文件存放目录
DATAPUMP DESTINATION 数据泵导出文件存放目录(可选)
REMAP TABLE 恢复到新表,如 schema.table:schema.new_table
NOTABLEIMPORT 只生成dump文件,不导入目标库

2.4 适用场景

RMAN 单表恢复适用于以下场景:

场景 说明
小表恢复 恢复单张或某几张表,但 Restore Database 代价太高
逻辑损坏恢复 恢复有逻辑损坏或被误删除的表
Undo 覆盖 Flashback Table 不可用(Undo 数据已覆盖)
DDL 操作后恢复 Flashback Table 不支持的结构变更后回退(如 TRUNCATE)

2.5 限制条件

⚠️ 以下情况无法使用 RECOVER TABLE

限制 说明
SYS 用户表 SYS 用户下的表或分区无法恢复
系统表空间 存储于 SYSAUX 和 SYSTEM 表空间的表无法恢复
Standby 库 备库上不能进行恢复
NOT NULL 约束 使用 REMAP 时,有 NOT NULL 约束的表无法恢复
读写模式 目标数据库必须置于读写模式
归档模式 目标数据库必须置于归档模式
兼容性 恢复单表分区需要 COMPATIBLE >= 11.1.0

2.6 时间点指定方式

sql 复制代码
-- 方式1:SCN号
RECOVER TABLE "TEST"."TEXT" UNTIL SCN 1234567 AUXILIARY DESTINATION '/backup';

-- 方式2:日志序列号
RECOVER TABLE "TEST"."TEXT" UNTIL LOGSEQ 100 AUXILIARY DESTINATION '/backup';

-- 方式3:时间(推荐)
RECOVER TABLE "TEST"."TEXT" 
UNTIL TIME "to_date('2026-04-13 16:38:00','yyyy-mm-dd hh24:mi:ss')"
AUXILIARY DESTINATION '/backup';

-- 方式4:相对时间
RECOVER TABLE "TEST"."TEXT" UNTIL TIME "SYSDATE-7" AUXILIARY DESTINATION '/backup';

3 工作原理

3.1 内存要求

⚠️ 关键 :辅助实例启动时会读取源库的参数文件进行 1:1 clone ,需要加载与主库相同的 SGA_MAX_SIZE

如果 SGA_MAX_SIZE * 2 > 物理内存,则执行命令会失败!

项目 说明
主数据库 SGA sga_max_size,占用内存
辅助实例 SGA 1:1 clone 源库参数,也需要 sga_max_size
所需内存 主库 sga_max_size + 辅助实例 sga_max_size < 物理内存

3.2 当前环境分析

复制代码
物理内存:8.6GB
主库 sga_max_size:5328MB
辅助实例 sga_max_size:5328MB(1:1 clone)
总计需求:10656MB > 8.6GB ❌

3.3 报错分析

复制代码
RMAN-04014: startup failed: ORA-27125: unable to create shared memory segment
Linux-x86_64 Error: 28: No space left on device

原因:物理内存不足,辅助实例需要与主库相同的 sga_max_size(1:1 clone),导致总内存需求超过物理内存。

解决方案

  1. 减小主库 sga_max_size 后重启
  2. 使用 NOTABLEIMPORT(不启动辅助实例)
  3. 使用闪回查询

3.4 解决方案:减小 sga_max_size

查看源库参数文件:

sql 复制代码
SQL> SHOW PARAMETER sga_max_size;
SQL> SHOW PARAMETER sga_target;

辅助实例会 1:1 clone 源库的参数文件,因此需要同时加载两个相同大小的 SGA。

sql 复制代码
-- 减小 sga_max_size(需要重启数据库生效)
ALTER SYSTEM SET sga_max_size=2048M SCOPE=SPFILE;
ALTER SYSTEM SET sga_target=2048M SCOPE=SPFILE;

重启数据库后,sga_max_size 将降至 2GB,辅助实例有足够内存启动(2GB + 2GB = 4GB < 8.6GB)。

3.5 备份要求

⚠️ 必须存在以下备份

备份类型 说明
完整数据库备份 至少要有 SYSTEM、UNDO、SYSAUX 表空间备份
表空间相关备份 包含需要恢复的表的表空间备份
PDB 模式额外要求 需要备份 Root Container 的 SYSTEM、SYSAUX、UNDO,以及 PDB 的相关表空间

3.6 磁盘空间要求

目录 空间要求
AUXILIARY DESTINATION 需要存放辅助实例数据文件,约 2-3 倍表大小
DATAPUMP DESTINATION 需要存放数据泵导出文件,约表大小

4 操作步骤

4.1 预处理检查清单

  • 确认物理内存充足(SGA × 2 < 物理内存)
  • 创建辅助实例目录并授权
  • 确认 RMAN 备份有效
  • 确定正确的恢复时间点
  • 确认需要恢复的表名和所属用户(PDB模式需指定PDB)

4.2 创建辅助目录

bash 复制代码
# 以 root 用户执行
mkdir -p /backup/tablerecovery
chown oracle:oinstall /backup/tablerecovery
chmod 755 /backup/tablerecovery

4.3 检查备份可用性

bash 复制代码
# 连接 RMAN
rman target /

# 查看备份
LIST BACKUP OF DATABASE;
LIST ARCHIVELOG ALL;

4.4 确认删除时间点

sql 复制代码
-- 使用闪回查询确认表删除前的时间
SELECT * FROM schema.table_name 
AS OF TIMESTAMP TO_TIMESTAMP('2026-04-13 16:35:00','yyyy-mm-dd hh24:mi:ss');

4.5 执行恢复

恢复到原表
sql 复制代码
RMAN> RECOVER TABLE "TEST"."TEXT"
UNTIL TIME "to_date('2026-04-13 16:38:00','yyyy-mm-dd hh24:mi:ss')"
AUXILIARY DESTINATION '/u01/app/oracle/aux_instance';
PDB模式恢复到原表
sql 复制代码
RMAN> RECOVER TABLE "LUCIFER"."LUCIFER" OF PLUGGABLE DATABASE lucifer
UNTIL TIME "to_date('2022-02-10 16:12:00','yyyy-mm-dd hh24:mi:ss')"
AUXILIARY DESTINATION '/backup/tablerecovery/';
恢复到新表(REMAP)
sql 复制代码
RMAN> RECOVER TABLE "TEST"."TEXT"
UNTIL TIME "to_date('2026-04-13 16:38:00','yyyy-mm-dd hh24:mi:ss')"
REMAP TABLE 'TEST.TEXT:TEST.TEXT_BAK'
AUXILIARY DESTINATION '/u01/app/oracle/aux_instance';

4.6 验证恢复结果

sql 复制代码
-- 查询恢复后的表
SELECT COUNT(*) FROM "TEST"."TEXT";

-- 如果使用了REMAP,检查新表
SELECT * FROM "TEST"."TEXT_BAK";

5 成功案例日志

5.1 PDB模式恢复日志

log 复制代码
RMAN> RECOVER TABLE lucifer.lucifer OF PLUGGABLE DATABASE lucifer
UNTIL TIME  "to_date('2022-02-10 16:12:00','yyyy-mm-dd hh24:mi:ss')"
AUXILIARY DESTINATION '/backup/tablereovery/';

Starting recover at 10-FEB-22
using target database control file instead of recovery catalog
allocated channel: ORA_DISK_1
channel ORA_DISK_1: SID=1588 device type=DISK
RMAN-05026: warning: presuming following set of tablespaces applies to specified point-in-time

List of tablespaces expected to have UNDO segments
Tablespace SYSTEM
Tablespace LUCIFER:SYSTEM
Tablespace UNDOTBS1
Tablespace LUCIFER:UNDOTBS1

Creating automatic instance, with SID='wtrc'

initialization parameters used for automatic instance:
db_name=ORCL
db_unique_name=wtrc_pitr_lucifer_ORCL
compatible=19.0.0
db_block_size=8192
db_files=200
diagnostic_dest=/u01/app/oracle
_system_trig_enabled=FALSE
sga_target=2048M
processes=200
db_create_file_dest=/backup/tablereovery/
log_archive_dest_1='location=/backup/tablereovery/'
enable_pluggable_database=true
_clone_one_pdb_recovery=true
#No auxiliary parameter file used

starting up automatic instance ORCL

Oracle instance started

Total System Global Area    2147482136 bytes

Fixed Size                     9136664 bytes
Variable Size                486539264 bytes
Database Buffers            1644167168 bytes
Redo Buffers                   7639040 bytes
Automatic instance created

5.2 数据导出和导入

log 复制代码
Performing export of tables...
   EXPDP> Starting "SYS"."TSPITR_EXP_wtrc_isse":
   EXPDP> Processing object type TABLE_EXPORT/TABLE/TABLE_DATA
   EXPDP> . . exported "LUCIFER"."LUCIFER"                         5.515 KB       3 rows
   EXPDP> Dump file set for SYS.TSPITR_EXP_wtrc_isse is:
   EXPDP>   /backup/tablereovery/tspitr_wtrc_94954.dmp
   EXPDP> Job "SYS"."TSPITR_EXP_wtrc_isse" successfully completed

Performing import of tables...
   IMPDP> Starting "SYS"."TSPITR_IMP_wtrc_mvyj":
   IMPDP> Processing object type TABLE_EXPORT/TABLE/TABLE
   IMPDP> . . imported "LUCIFER"."LUCIFER"                         5.515 KB       3 rows
   IMPDP> Job "SYS"."TSPITR_IMP_wtrc_mvyj" successfully completed

Removing automatic instance
Automatic instance removed
Finished recover at 10-FEB-22

6 常见错误

错误 原因 解决方案
ORA-27125 共享内存 sga_max_size × 2 > 物理内存 减小 sga_max_size
RMAN-05001 文件冲突 auxiliary file 与目标库文件冲突 指定不同的 AUXILIARY DESTINATION
RMAN-05002 aborting TSPITR 辅助实例文件冲突 使用独立的辅助实例目录
ORA-19913 无法恢复 时间点无效 指定更早的时间点
ORA-38788 表不支持闪回 RMAN 自动处理,无需开启
RMAN-05026 需要 UNDO 确保 SYSTEM 和 UNDO 表空间在线
RMAN-05093 辅助实例启动失败 检查内存、目录权限、内核参数

7 备选方案

7.1 使用 NOTABLEIMPORT(只导出 dump,不导入)

sql 复制代码
RECOVER TABLE "TEST"."TEXT"
UNTIL TIME "to_date('2026-04-13 16:38:00','yyyy-mm-dd hh24:mi:ss')"
AUXILIARY DESTINATION '/backup/auxiliary'
DATAPUMP DESTINATION '/backup'
NOTABLEIMPORT;

然后手动导入:

bash 复制代码
impdp TEST/TEST directory=backup_dir dumpfile=tspitr_*.dmp table_exists_action=REPLACE

⚠️ 注意 :NOTABLEIMPORT 只是不导入数据,辅助实例仍然会创建,因此 AUXILIARY DESTINATION 仍需指定!

bash 复制代码
impdp TEST/TEST directory=backup_dir dumpfile=tspitr_*.dmp table_exists_action=REPLACE

7.2 使用闪回查询(数据量小)

sql 复制代码
-- 直接从 UNDO 恢复
INSERT INTO "TEST"."TEXT"
SELECT * FROM "TEST"."TEXT" 
AS OF TIMESTAMP TO_TIMESTAMP('2026-04-13 16:35:00','yyyy-mm-dd hh24:mi:ss');
COMMIT;

7.3 使用 TSPITR(表空间时间点恢复)

bash 复制代码
# 使用 RMAN TSPITR
rman target /

RECOVER TABLESPACE test_ts UNTIL TIME "to_date('2026-04-13 16:38:00','yyyy-mm-dd hh24:mi:ss')";

8 注意事项

  1. 需要指定误删表的 PDB(如果是PDB模式)
  2. 需要指定误删数据的时间点,精确到秒
  3. 需要指定恢复辅助目录,且目录要有足够磁盘空间
  4. 确保物理内存充足,否则会报 ORA-27125
  5. 恢复完成后会自动清理辅助实例临时文件
  6. 如果表恢复后需要导入到原表,先使用 REMAP TABLE 恢复到新表,再手动插入
相关推荐
Dream of maid2 小时前
Mysql(6)关联查询
数据库·mysql
lonelyhiker2 小时前
cas学习笔记
数据库·笔记·学习
云淡风轻~窗明几净2 小时前
ubuntu的lazarus的Tline/TeaLine组件的构思
linux·数据库·ubuntu
雒珣2 小时前
Qt实现命令行参数功能示例:QCommandLineParser
开发语言·数据库·qt
知识分享小能手2 小时前
MongoDB入门学习教程,从入门到精通,MongoDB备份完全指南(23)
数据库·学习·mongodb
源来猿往2 小时前
mysql转postgresql【平移】
数据库·mysql·postgresql
爱学习的小囧2 小时前
VMFS与NFS性能对比(含场景适配+实操建议)
运维·数据库·自动化·esxi·虚拟化
byte轻骑兵2 小时前
Apache IoTDB 技术特性与大数据时序数据库选型实践
大数据·数据库·人工智能·物联网·时序数据库
Dream of maid2 小时前
Mysql(7)子查询
android·数据库·mysql