必须在CDB$ROOT中执行RECOVER TABLE并显式指定PDB名和表名;连接RMAN前须确认容器为CDB$ROOT,否则命令静默无效;需指定UNTIL TIME/SCN、AUXILIARY DESTINATION,且恢复后需手动重建索引、约束、触发器。

必须在CDB$ROOT中执行RECOVER TABLE,且显式指定PDB名和表名;否则命令静默无效或报ORA-19554/ORA-65096,根本不会启动恢复流程。
连接RMAN前必须确认容器上下文是CDB$ROOT
哪怕你要恢复的是PDB1.SALES.ORDER_HEADER,RMAN也绝不允许你用tnsnames.ora里指向PDB1的服务名连接。一旦连进PDB,RECOVER TABLE就变成“语法合法但逻辑失效”——不报错、不失败、也不干活。
实操验证步骤:
- 先用
sqlplus / as sysdba执行SELECT SYS_CONTEXT('USERENV', 'CON_NAME') FROM DUAL,结果必须是CDB$ROOT - 检查
ORACLE_SID是否指向CDB实例名(如orcl),不是PDB服务名 - OS用户必须是
oracle,且ORACLE_HOME已正确加载
RECOVER TABLE命令必须带UNTIL TIME或UNTIL SCN,且时间点要早于误操作
TRUNCATE或DROP PURGE后,表段元数据从数据字典消失,RECOVER TABLE只对“该时间点还存在”的对象有效。归档日志缺一个序列号不一定失败,但若缺的是DDL前后那几个,就会卡在ORA-19921: no arc。
查误操作时间的可靠方式:
- 用LogMiner:
EXEC DBMS_LOGMNR.START_LOGMNR(OPTIONS => DBMS_LOGMNR.DICT_FROM_ONLINE_CATALOG + DBMS_LOGMNR.COMMITTED_DATA_ONLY),再查V$LOGMNR_CONTENTS - 目标时间建议比误操作时间早3分钟,避开日志切换边界
- 示例命令:
RECOVER TABLE PDB1.SALES.ORDER_HEADER UNTIL TIME "TO_DATE('20260915 142200','yyyymmdd hh24miss')" AUXILIARY DESTINATION '/u01/oradata/aux';
AUXILIARY DESTINATION必须显式指定且空间充足
不指定AUXILIARY DESTINATION,RMAN会卡在creating auxiliary instance阶段,错误不明确,容易误判为网络或权限问题。这个临时库需要足够空间(通常为被恢复PDB数据文件总大小的2–3倍)。
关键检查项:
- 路径需有足够空间,且Oracle用户可读写:
chown oracle:oinstall /u01/oradata/aux、chmod 755 /u01/oradata/aux - 如果
FAST_RECOVERY_AREA空间不足,RECOVER启动辅助实例时会卡住,必须显式加AUXILIARY DESTINATION - 若原表名已存在,必须加
REMAP TABLE 'PDB1.SALES.ORDER_HEADER':'PDB1.SALES.ORDER_HEADER_BAK'
恢复后索引、约束、触发器不会自动重建
RECOVER TABLE只导出数据行,不导出依赖对象定义。恢复后的表能查到数据,但可能缺少主键、外键、函数索引甚至唯一约束——业务逻辑可能悄然失效,这点最容易被忽略。
必须手动补全:
- 用
DBMS_METADATA.GET_DDL提取原表的索引、约束、触发器定义 - 检查
DBA_CONSTRAINTS和DBA_INDEXES确认缺失项 - 特别注意
ENABLE NOVALIDATE约束,它们不会在恢复过程中被重建,但会影响后续DML
真正麻烦的不是命令写不对,而是恢复完表能查出数据就以为万事大吉——约束和索引没重建,应用层一写入就报错,问题反而更隐蔽。


















