Oracle误truncate操作恢复(一)

来源:这里教程网 时间:2026-03-03 21:34:37 作者:

1 truncate 原理介绍

Oracle数据库truncate table时只产生非常少的redo和undo,就实现了清空表数据并降低表HWM的功能。 有兴趣的同学 可以通过10046以及redo dump去分析truncate的整个操作过程 。你会 看到,Oracle truncate table的实质是在不修改数据块的情况下,通过修改segment header的data_object_id,hwm,extent map,aux map等信息来实现清空表的目的 其中还涉及数据字典基表以及L1、L2位图块的修改,truncate操作存储数据的数据块没有产生任何redo和undo,但是segment header,位图块,数据字典基表还是会产生redo和undo。

2 、使用备份恢复

1)利用逻辑备份恢复;如无特殊需求,只恢复误操作的业务表即可;缺点:恢复出来的数据固定在备份的时间点。有部分数据会丢失。 示例: nohup impdp \'\/ as sysdba\' directory= datad ir dumpfile=full_db.dmp logfile=impdb.log tables= U1 . TABLE1 , U2 . TABLE2  &

2)利用物理备份与归档前滚的方式,恢复到误操作的前几分钟或几秒钟。此需要精确误操作的时间节点,且数据库较大的情况,恢复时间较长 示例: RMAN>   restore controlfile from '/u01/backup/ctl_0gnpvd65_1_1.ctl';                                            RMAN>   restore database;     RMAN>   recover database until time '2020-06-22   13:15:24' using backup controlfile; RMAN>   alter database open resetlogs;

3 、使用闪回恢复

1)有物理备库,且备库端开启了全库级别的闪回,保障故障时间在闪回范围内,且有之后的归档日志。 示例: SQL> ALTER DATABASE RECOVER MANAGED STANDBY DATABASE CANCEL; RMAN> flashback database to time = "TO_DATA('2024-10-22 12:34:00','yyyy-mm-dd hh24:mi:ss')";

4 、使用 FY_Recover_Data 恢复

当尝试使用该存储过程包恢复数据,其前提是表数据块未被覆盖。原理:如果我们已经有一套元数据及数据块,然后将被 TRUNCATE的用户数据块的内容取代其用户数据块的内容,是否可以“骗”过Oracle,让它读出这些数据呢?

回顾一下表扫描的过程,这个方法应该是可行的。我们只要想办法构造出一个结构相同、且具有完整元数据信息和格式化了的用户数据块的傀儡表对象,然后将被 TRUNCATE的用户数据块找出,再将其数据内容部分嫁接到傀儡对象的用户数据块,使Oracle以外这是傀儡对象的数据,就能让Oracle扫描并读出数据内容。其原理用图示描述如下:

FY_Recover_Data对于表恢复的支持性如下:

压缩表 

支持 

索引组织表

支持

分区表 

支持  

行链接/行迁移

不支持

标准SQL类型

支持

BLOB/CLOB

支持Store in Row

离线恢复

支持

操作系统平台

全部 

数据库版本

9i以上

  创建测试数据: SQL> conn mary/mary Connected. SQL> create table mary.test_obj as select * from dba_objects; Table created. SQL> select count(*) from mary.test_obj;   COUNT(*) ----------      86295

  误操作模拟: SQL> truncate table mary.test_obj; Table truncated. SQL> select count(*) from mary.test_obj;   COUNT(*) ----------          0 SQL> select file_id from dba_extents where segment_name='TEST_OBJ';    FILE_ID ----------          4 注:保障新数据已经停止写入,老的数据块没有被覆盖。

  FY_Recover_Data 包安装: SQL> @/home/oracle/FY_Recover_Data.pck

  执行存储过程恢复数据: EXEC FY_RECOVER_DATA.recover_truncated_table(' 用户 ', ' 表名 ', 数据文件编号 , ' 备份路径 ', ' 数据文件路径 ');   使用 FY_Recover_Data 包恢复数据: SQL> exec fy_recover_data.recover_truncated_table('MARY','TEST_OBJ'); SQL> select count(*) from mary.test_obj$$;   COUNT(*) ----------      86295 SQL> insert into mary.test_obj select * from mary.test_obj$$; 86295 rows created. SQL> commit; Commit complete.

  残存清理: SQL> drop tablespace FY_REC_DATA INCLUDING CONTENTS and datafiles; Tablespace dropped. SQL> drop tablespace FY_RST_DATA INCLUDING CONTENTS and datafiles; Tablespace dropped.

相关推荐