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.
