ITPub博客

首页 > 数据库 > Oracle > 闪回搞不定时怎么办?Oracle数据恢复的终极武器

闪回搞不定时怎么办?Oracle数据恢复的终极武器

原创 Oracle 作者:marui 时间:2026-07-02 17:45:57 0 删除 编辑

Oracle数据恢复进阶实战:LogMiner日志挖掘与TRUNCATE恢复全攻略

 

大家好,我是睿。

 

上一期我们聊了Oracle闪回技术全家桶,从闪回查询到闪回数据库,把6种闪回方式全部实操了一遍。文章最后我留了个预告——当闪回技术搞不定的时候,该怎么办?

 

现实中,DBA经常遇到这些棘手场景:

• DML 误操作后, redo 日志已经被归档,在线日志里找不到

• 需要精确审计 " 谁在什么时间改了什么数据 "

• TRUNCATE 误删了核心业务表,闪回技术无能为力

• 没有开归档,闪回区也过期了

 

今天这篇文章,我们就来掌握几把终极武器:LogMiner日志挖掘和TRUNCATE后的数据恢复方案。这些是闪回之外的最后防线,每一个DBA都应该烂熟于心。

 

一、LogMiner 日志挖掘

 

1.1 LogMiner 能做什么

LogMiner是Oracle自带的redo日志分析工具,它能读取redo log和archive log,把二进制日志翻译成可读的SQL语句。核心能力:

• 查看 DML 操作的 SQL_REDO (重放)和 SQL_UNDO (回滚)

• 精确审计:谁、什么时间、对哪张表、做了什么操作

• 追踪数据变更历史,辅助故障定位

• 不需要额外 license ,标准版即可使用

 

1.2 前置条件与配置

开启补充日志(必须):

-- 开启最小补充日志( LogMiner 的前提)

ALTER DATABASE ADD SUPPLEMENTAL LOG DATA;

 

-- 验证

SELECT supplemental_log_data_min FROM v$database;

-- SUPPLEMENTAL_LOG_DATA_MIN

-- --------------------------

-- YES

 

全库级别补充日志(可选,获取完整SQL_UNDO):

-- 全列补充日志(生成的 SQL_UNDO 更完整)

ALTER DATABASE ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS;

 

-- 或者针对特定表

ALTER TABLE mary.test_logminer ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS;

 

1.3 实战:挖掘在线 redo 日志

下面用一个完整的实验来演示整个流程。

 

Step 1:准备测试数据

-- 1.1 创建 mary 用户并授权(如已有可跳过)

 CREATE USER mary IDENTIFIED BY mary DEFAULT TABLESPACE mary ;

 GRANT CONNECT, RESOURCE TO mary;

 GRANT EXECUTE_CATALOG_ROLE TO mary;  -- LogMiner 需要此权限

 

-- 1.2 以 mary 用户创建测试表

 CONN mary/mary

 CREATE TABLE mary.test_logminer (

      id NUMBER PRIMARY KEY,

      name VARCHAR2(50),

      salary NUMBER

    );

 

-- 1.3 插入测试数据

 INSERT INTO mary.test_logminer VALUES (1, 'Alice', 15000);

 INSERT INTO mary.test_logminer VALUES (2, 'Bob', 18000);

 INSERT INTO mary.test_logminer VALUES (3, 'Charlie', 20000);

 COMMIT;

 

-- 1.4 验证数据

 SELECT * FROM mary.test_logminer;

        ID NAME                       SALARY

---------- ------------------------------ ----------

         1 Alice                         15000

         2 Bob                           18000

         3 Charlie                       20000

 

Step 2:执行DML操作(模拟误操作)

-- 2.1 模拟误操作: UPDATE + DELETE

 UPDATE mary.test_logminer SET salary = 99999 WHERE id = 1;

1 row updated.

 

 DELETE FROM mary.test_logminer WHERE id = 2;

1 row deleted.

 

 COMMIT;

 

-- 2.2 查看误操作后的数据

 SELECT * FROM mary.test_logminer;

        ID NAME                       SALARY

---------- ------------------------------ ----------

         1 Alice                         99999  -- 被改了

                                                       -- Bob 被删了

         3 Charlie                       20000  

 

Step 3:添加日志文件到LogMiner

-- 查看当前在线 redo 日志

set linesize 500

set pagesize 100

col member for a40

col status for a10

SELECT a.THREAD#, a.GROUP#, b.MEMBER, a.BYTES / 1024 / 1024 AS SIZE_MB  ,a.status

FROM V$LOG a JOIN V$LOGFILE b

ON a.GROUP# = b.GROUP# ORDER BY a.THREAD#, a.GROUP#;

 

    THREAD#     GROUP# MEMBER                                      SIZE_MB STATUS

---------- ---------- ---------------------------------------- ---------- ----------

          1          1 /u01/app/oracle/oradata/NOCDB/onlinelog/        200 INACTIVE

                       o1_mf_1_nkf4jk6f_.log

          1          1 /u01/app/oracle/fast_recovery_area/NOCDB        200 INACTIVE

                       /onlinelog/o1_mf_1_nkf4jmq9_.log

          1          2 /u01/app/oracle/oradata/NOCDB/onlinelog/        200 INACTIVE

                       o1_mf_2_nkf4jk8k_.log

          1          2 /u01/app/oracle/fast_recovery_area/NOCDB        200 INACTIVE

                       /onlinelog/o1_mf_2_nkf4jsps_.log

          1          3 /u01/app/oracle/oradata/NOCDB/onlinelog/        200 CURRENT

                       o1_mf_3_nkf4jk99_.log

          1          3 /u01/app/oracle/fast_recovery_area/NOCDB        200 CURRENT

                       /onlinelog/o1_mf_3_nkf4jz1z_.log

6 rows selected.

 

-- 添加要分析的日志文件

  EXEC DBMS_LOGMNR.ADD_LOGFILE(LOGFILENAME => '/u01/app/oracle/fast_recovery_area/NOCDB/onlinelog/o1_mf_3_nkf4jz1z_.log',OPTIONS => DBMS_LOGMNR.NEW);

 

Step 4:启动LogMiner(使用在线数据字典)

EXEC DBMS_LOGMNR.START_LOGMNR(Options => DBMS_LOGMNR.DICT_FROM_ONLINE_CATALOG);

 

Step 5:查询分析结果

-- 查看所有 DML 操作

  SELECT timestamp, sql_redo, sql_undo

     FROM v$logmnr_contents

     WHERE seg_name = 'TEST_LOGMINER'

     ORDER BY timestamp;

 

TIMESTAMP  SQL_REDO                                    SQL_UNDO

---------- --------------------------- -----------------

01-DEC-22

insert into "MARY"."TEST_LOGMINER"("ID","NAME","SALARY") values ('1','Alice','15000');

delete from "MARY"."TEST_LOGMINER" where "ID" = '1' and "NAME" = 'Alice' and "SALARY" = '15000' and ROWID = 'AAAbZOAAFAAAAA7AAA';

 

01-DEC-22

insert into "MARY"."TEST_LOGMINER"("ID","NAME","SALARY") values ('2','Bob','18000');

delete from "MARY"."TEST_LOGMINER" where "ID" = '2' and "NAME" = 'Bob' and "SALARY" = '18000' and ROWID = 'AAAbZOAAFAAAAA7AAB';

 

01-DEC-22

insert into "MARY"."TEST_LOGMINER"("ID","NAME","SALARY") values ('3','Charlie','20000');

delete from "MARY"."TEST_LOGMINER" where "ID" = '3' and "NAME" = 'Charlie' and "SALARY" = '20000' and ROWID = 'AAAbZOAAFAAAAA7AAC';

 

01-DEC-22

update "MARY"."TEST_LOGMINER" set "SALARY" = '99999' where "SALARY" = '15000' and ROWID = 'AAAbZOAAFAAAAA7AAA';

update "MARY"."TEST_LOGMINER" set "SALARY" = '15000' where "SALARY" = '99999' and ROWID = 'AAAbZOAAFAAAAA7AAA';

 

01-DEC-22

delete from "MARY"."TEST_LOGMINER" where "ID" = '2' and "NAME" = 'Bob' and "SALARY" = '18000' and ROWID = 'AAAbZOAAFAAAAA7AAB';

insert into "MARY"."TEST_LOGMINER"("ID","NAME","SALARY") values ('2','Bob','18000');

 

看到了吗?SQL_REDO是实际执行的操作,SQL_UNDO是回滚操作——这就是恢复数据的关键。

 

Step 6:结束分析

EXEC DBMS_LOGMNR.END_LOGMNR;

 

1.4 实战技巧:精准定位目标操作

生产环境的日志量动辄几十上百个G,直接全量查询等于大海捞针。分享几个我常用的精准过滤技巧:

 

-- 按时间范围过滤

SELECT timestamp, sql_redo, sql_undo

FROM v$logmnr_contents

WHERE timestamp BETWEEN

  TO_DATE('2026-06-30 10:00:00', 'YYYY-MM-DD HH24:MI:SS')

  AND TO_DATE('2026-06-30 11:00:00', 'YYYY-MM-DD HH24:MI:SS')

AND seg_owner = 'MARY'

AND operation = 'DELETE';

 

-- 按 SCN 范围过滤(更精确)

SELECT timestamp, sql_redo, sql_undo

FROM v$logmnr_contents

WHERE scn BETWEEN 59447386 AND 59449766

AND seg_name LIKE 'TEST%';

 

 

1.5 分析归档日志

实际场景中,redo日志往往已经被归档。这时候同样可以分析归档日志:

 

-- 查看归档日志列表

 SELECT name, sequence#, first_time, next_time

    FROM v$archived_log

    WHERE dest_id = 1

    ORDER BY sequence#;

 

-- 添加多个归档日志

EXEC DBMS_LOGMNR.ADD_LOGFILE( LogFileName =>' /u01/app/oracle/fast_recovery_area/NOCDB/archivelog/202 6 _ 07 _01/o1_mf_1_1222_krh55h1c_.arc ',Options => DBMS_LOGMNR.NEW);

EXEC DBMS_LOGMNR.ADD_LOGFILE( LogFileName =>' /u01/app/oracle/fast_recovery_area/NOCDB/archivelog/202 6 _ 07 _01/o1_mf_1_1221_krh3gm1w_.arc ',Options => DBMS_LOGMNR.NEW);

 

-- 跨库分析时 , 在源库(被分析的库)上执行

BEGIN DBMS_LOGMNR_D.BUILD( dictionary_filename => 'dict.ora', dictionary_location => '/u01/logmnr/', options => DBMS_LOGMNR_D.STORE_IN_FLAT_FILE ); END; /

-- 在第三方数据库做日志分析, 使用字典文件启动

EXEC DBMS_LOGMNR.START_LOGMNR( DictFileName => '/u01/logmnr/dict.ora', Options => DBMS_LOGMNR.DICT_FROM_REDO_LOGS);

 

1.6 LogMiner 的局限性与注意事项

1. TRUNCATE 无法恢复: TRUNCATE 是 DDL 操作,只修改 segment header ,

    不产生逐行的redo/undo 日志。 LogMiner 只能看到 "TRUNCATE TABLE xxx"

    的记录,但没有SQL_UNDO ,无法通过重放来恢复数据。

    恢复TRUNCATE 需要其他方案,见第二章。

 

2. 日志保留时间:在线 redo 日志会被循环覆盖,归档日志也 被 手动或自动清理。不能依赖" 总能找到日志 " 。

 

3. 性能影响: LogMiner 分析大量日志时消耗 CPU 和内存,

    建议在测试环境执行。

 

4. LOB 和 LONG 类型:对大字段的支持有限, SQL_UNDO 可能不完整。

 

二、TRUNCATE 后的数据恢复

 

在动手恢复之前,先搞清楚TRUNCATE的本质:

• TRUNCATE 是 DDL 操作,会修改 segment header 中的 data_object_id

• 重置 High Water Mark ( HWM )和 extent map

• 不会逐行删除数据块中的内容

• 不产生数据级别的 redo/undo 日志

• 默认情况下会释放存储空间

 

关键原则:只要数据块没有被覆盖,就有机会恢复!

 

公共测试环境准备:

先创建测试表并批量插入1000条数据,后续各方案的演示均基于这张表。

-- 1. 创建测试表

  sqlplus mary/ mary

 CREATE TABLE mary.employees (

      emp_id    NUMBER PRIMARY KEY,

      emp_name  VARCHAR2(50),

      dept      VARCHAR2(30),

      salary    NUMBER

    );

 

-- 2. 批量插入 1000 条测试数据

 BEGIN

      FOR i IN 1..1000 LOOP

        INSERT INTO mary.employees VALUES (

          i,

          'EMP_' || LPAD(i, 4, '0'),

          CASE MOD(i, 4)

            WHEN 0 THEN 'IT'

            WHEN 1 THEN 'Sales'

            WHEN 2 THEN 'HR'

           WHEN 3 THEN 'Finance'

         END,

         10000 + MOD(i, 500) * 30

       );

     END LOOP;

     COMMIT;

   END;

   /

 

-- 3. 验证数据量

 SELECT COUNT(*) FROM mary.employees;

  COUNT(*)

----------

      1000

 

-- 4. 查看前几条数据样例

 SELECT * FROM mary.employees WHERE ROWNUM <= 5 ORDER BY emp_id;

 

    EMP_ID EMP_NAME  DEPT       SALARY

---------- ---------- ---------- ----------

         1 EMP_0001  Sales        10030

         2 EMP_0002  HR           10060

         3 EMP_0003  Finance      10090

         4 EMP_0004  IT           10120

         5 EMP_0005  Sales        10150

 

2.1 方案一:容灾库闪回数据库恢复

闪回数据库是恢复TRUNCATE数据最快的方案。但在生产库上直接做FLASHBACK DATABASE影响面过大,绝对不可行。正确的做法是:在容灾库上做闪回,以read only模式打开,再通过dblink把数据反向插回生产库。

前提条件:容灾库(Physical Standby)长期开启Flashback Database。

操作步骤:

-- ===== 以下步骤在容灾库(备库)执行 =====

 

-- 1. 暂停容灾库的 redo apply

ALTER DATABASE RECOVER MANAGED STANDBY DATABASE CANCEL;

 

-- 2. 在容灾库执行闪回到 TRUNCATE 之前的时间点

FLASHBACK DATABASE TO TIMESTAMP

  TO_TIMESTAMP('2026-06-30 10:00:00', 'YYYY-MM-DD HH24:MI:SS');

 

-- 3. 以 read only 方式打开容灾库

ALTER DATABASE OPEN READ ONLY;

 

-- 4. 验证数据已恢复

SELECT COUNT(*) FROM mary.employees;

  COUNT(*)

----------

      1000

 

通过dblink将数据反向回传到生产库:

-- ===== 在生产库执行 =====

 

-- 5. 在生产库创建到容灾库的 dblink

CREATE DATABASE LINK to_standby

CONNECT TO mary IDENTIFIED BY oracle

USING '(DESCRIPTION =

(ADDRESS_LIST =

(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.110.101)(PORT = 1521))

)

(CONNECT_DATA =

(SERVICE_NAME = nocdb)

)

)';

 

-- 6. 从容灾库拉回数据

INSERT INTO mary.employees

  SELECT * FROM mary.employees@to_standby;

commit;

 

-- 7. 验证

SELECT COUNT(*) FROM mary.employees;

  COUNT(*)

----------

      1000

 

恢复完成后,容灾库重新同步:

-- ===== 在容灾库执行 =====

-- 8. 容灾库重新 flashback 到最新状态,恢复同步

ALTER DATABASE RECOVER MANAGED STANDBY DATABASE

  USING CURRENT LOGFILE DISCONNECT;

 

这个方案的核心优势在于:不影响生产库正常运行,不需要RESETLOGS,数据通过dblink精准回传。唯一前提是容灾库必须提前开启Flashback Database——这也是我一直强调容灾库要开flashback的根本原因。

 

2.2 方案二: RMAN 备份异机恢复

如果容灾库没有开Flashback,或者手头有RMAN备份,可以通过异机恢复来抢救数据。核心原则不变:所有操作在异机(辅助实例)上完成,绝不动生产库。

 

方法A:异机全库恢复(最有效,但最耗时、耗资源)

-- 在异机(辅助实例)上执行

 

-- 1. 在异机准备参数文件、创建目录结构

-- 2. 启动辅助实例到 nomount

STARTUP NOMOUNT PFILE='/tmp/pfile.ora';

 

-- 3. 全库恢复到 TRUNCATE 之前的 SCN

RMAN> RUN {

  SET UNTIL SCN 59464891 ;

  RESTORE DATABASE;

  RECOVER DATABASE;

  ALTER DATABASE OPEN RESETLOGS;

}

 

-- 4. 验证数据存在

SELECT COUNT(*) FROM mary.employees;

 

-- 5. 在生产库创建 dblink 连接到异机

CREATE DATABASE LINK to_aux

  CONNECT TO mary IDENTIFIED BY mary_password

  USING 'aux_tns';

 

-- 6. 从异机拉回数据

INSERT INTO mary.employees

  SELECT * FROM mary.employees@to_aux;

COMMIT;

 

-- 7. 恢复完成后关闭异机

SHUTDOWN IMMEDIATE;

 

方法A的优势是数据完整性100%有保证,缺点是耗时长(需要全库restore+recover),且需要一台空闲的辅助服务器,适合大型灾难场景。

 

方法B:异机表空间级恢复

-- 在异机执行

 

-- 1. 只恢复目标表空间(节省时间和空间)

准备 可用的 参数文件

准备创建控制文件的脚本,只保留必要的数据文件

 alter database backup controlfile to trace as '/soft/controlfile_reset.sql' resetlogs;

vi controlfile_reset.sql ( 只保留 system 、 sysaux 、 undo 、 temp 、 目标表空间 )

 

-- 目标环境执行:

STARTUP NOMOUNT

CREATE CONTROLFILE REUSE DATABASE "LOCALDB" RESETLOGS FORCE LOGGING ARCHIVELOG

    MAXLOGFILES 16

    MAXLOGMEMBERS 3

    MAXDATAFILES 100

    MAXINSTANCES 8

    MAXLOGHISTORY 292

LOGFILE

  GROUP 1 '/oradata/localdb/redo01.log'  SIZE 50M BLOCKSIZE 512,

  GROUP 2 '/oradata/localdb/redo02.log'  SIZE 50M BLOCKSIZE 512,

  GROUP 3 '/oradata/localdb/redo03.log'  SIZE 50M BLOCKSIZE 512

-- STANDBY LOGFILE

DATAFILE

  '/oradata/localdb/system01.dbf',

  '/oradata/localdb/sysaux01.dbf',

  '/oradata/localdb/undotbs01.dbf',

  '/oradata/localdb/mary01.dbf',

  '/oradata/localdb/mary03.dbf',

  '/oradata/localdb/mary02.dbf'

CHARACTER SET ZHS16GBK

;

RECOVER DATABASE USING BACKUP CONTROLFILE

ALTER TABLESPACE TEMP ADD TEMPFILE '/oradata/localdb/temp01.dbf' REUSE;

 

-- 启动到 mount 状态,恢复 system 、 sysaux 、 undo 、 目标表空间

rman target /

RUN {

   SET UNTIL SCN 5326681;

   RESTORE TABLESPACE mary;

   RESTORE TABLESPACE sysaux;

   RESTORE TABLESPACE system;

   RESTORE TABLESPACE undotbs1;

   RECOVER TABLESPACE mary;

   RECOVER TABLESPACE sysaux;

   RECOVER TABLESPACE system;

   RECOVER TABLESPACE undotbs1;

}

RMAN> recover database;

 

sqlplus / as sysdba

SQL> alter database open resetlogs;

SQL> select name from v$tablespace;

NAME

------------------------------

SYSTEM

SYSAUX

UNDOTBS1

MARY

TEMP

 

SQL> SELECT count(*) FROM mary.employees;

  COUNT(*)

----------

      1000

 

-- 2. 同样通过 dblink 在生产库拉取数据

INSERT INTO mary.employees

  SELECT * FROM mary.employees@to_aux;

COMMIT;

 

表空间级恢复的速度比全库恢复快得多,但需要注意:异机的文件路径、表空间名称等可能需要调整。可控性也不如全库恢复,实际使用要根据具体情况灵活判断。

 

2. 3 方案三:FY_RECOVER_DATA 存储过程包

FY_RECOVER_DATA是一个专门用于TRUNCATE恢复的工具包,核心原理是构造傀儡表,将被TRUNCATE表的数据块内容嫁接到傀儡对象上,从而实现数据恢复。

 

支持范围:

• 普通堆表( Heap Table )

• 压缩表( Compression )

• 索引组织表( IOT )

• 分区表

• BLOB/CLOB Store in Row

• 离线恢复( Offline Recovery )

• Oracle 9i 及以上,全平台支持

 

关于数据条数限制:

FY_RECOVER_DATA从数据块层面恢复数据,理论上没有硬性的条数限制。但实际恢复效果和性能受以下因素影响:

• 数据块是否已被覆盖:如果 TRUNCATE 后有大量写入操作,

   原数据块可能已被重用,这部分数据无法恢复

• 表的大小:超大表(几十 GB 以上)恢复时间较长

• 表空间剩余空间:恢复过程需要在同表空间创建傀儡对象,

   需要足够的空间

• 建议: TRUNCATE 后尽快执行恢复,减少数据块被覆盖的概率

 

实战演示:

-- 1. 模拟 TRUNCATE 误操作

 SELECT COUNT(*) FROM mary.employees;

  COUNT(*)

----------

      1000

 

 TRUNCATE TABLE mary.employees;

Table truncated.

 

-- 2. 确认数据已丢失

 SELECT COUNT(*) FROM mary.employees;

  COUNT(*)

----------

         0

 

-- 3. 加载 FY_RECOVER_DATA 包

SQL> @/soft/FY_Recover_Data.pck

Enter value for files:     (这里直接回车即可)

old  30:   --   1. Temp Restore and Recover tablespace & files                     ---

new  30:   --   1. Temp Restore and Recover tablespace                      ---

Package created.

Package body created.

 

-- 4. 执行恢复

SQL> exec fy_recover_data.recover_truncated_table('MARY','EMPLOYEES');

PL/SQL procedure successfully completed.

 

-- 5. 查看恢复结果

SQL> SELECT COUNT(*) FROM mary.employees$$;

   COUNT(*)

----------

       1000

 

-- 6. 将恢复的数据写回原表

 INSERT INTO mary.employees SELECT * FROM mary.employees$ $ ;

 COMMIT;

 

-- 7. 验证

 SELECT COUNT(*) FROM mary.employees;

  COUNT(*)

----------

      1000

 

恢复出来的数据会存储在以原表名加$$后缀的傀儡表中,确认数据无误后再导入原表。整个过程不需要停机,对生产环境的影响极小。

恢复完成后,别忘了清理 FY_RECOVER_DATA包自动创建的临时表空间:

SQL> drop tablespace FY_REC_DATA INCLUDING CONTENTS and datafiles;

Tablespace dropped.

SQL> drop tablespace FY_RST_DATA INCLUDING CONTENTS and datafiles;

Tablespace dropped.

 

 

2.4 方案四:第三方工具( ODU/DUL/PRM )

如果以上方案都不可用 ——没有容灾库闪回、没有RMAN备份、也没有FY_RECOVER_DATA包——还可以借助专业的数据恢复工具。需要提醒的是:ODU、DUL、PRM均为商业收费软件,网上能下载到的试用版通常有数据条数限制,生产环境使用需要购买正式授权。

工具

特点

适用场景

ODU (Oracle Data Unloader)

直接读取数据文件,不依赖实例,商业收费

表空间损坏、数据文件损坏

DUL (Database Unloader)

类似ODU,商业收费

极端场景下的数据抢救

PRM (Parnassus Recovery)

国产商业恢复工具,商业收费

支持ASM/RAC/加密表空间

 

本文以 Windows环境下的ODU为例,简单演示恢复流程。

ODU恢复流程示例:

-- 1. 将表空间 offline

 ALTER TABLESPACE mary OFFLINE;

 

-- 2. 复制数据文件到 ODU 所在的 Windows 服务器

 

-- 3. 进入 ODU 目录,修改 control.txt 文件,将文件路径根据实际情况修改

示例:

#ts  #fno  #rfno   filename    block_size

5   6   6  D:\workspace\test.dbf    8192

 

-- 4 . 使用 ODU 加载数据字典

. \ odu .exe

ODU> unload dict

 

-- 5 . 扫描 目标表空间

ODU> scan extent tablespace 5

 

-- 6 . 导出恢复的数据

ODU> unload table mary.employees object auto

生成 MARY_EMPLOYEES. ctl 、 MARY_EMPLOYEES. txt 两个文件

 

-- 7 . 用 sqlldr 将数据导入

SQL> alter tablespace mary online;

$ sqlldr userid=mary/mary control= MARY_EMPLOYEES .ctl

 

-- 8 . 验证恢复的数据

 SELECT COUNT(*) FROM mary.employees;

 

三、总结与实战建议

 

3.1 LogMiner 最佳实践

1. 日常开启最小补充日志,关键时刻不掉链子

2. 重要表开启全列补充日志

3. 分析时先用时间 /SCN/ 表名精准过滤,避免 大 量扫描

4. 大量日志分析建议在 异机 库进行,不影响生产

5. 定期清理不需要的归档日志,释放空间

 

3.2 预防 TRUNCATE 误操作的几条铁律

1. 做好用户的 权限 管理 ,只授予必要的 使用权限

2 . 容灾库务必开启 Flashback Database (关键时刻能救命)

3 . RMAN 备份策略:全备 + 增量 + 归档日志 尽量多的 保留

4 . 重要操作前记录 关键 时间 节点

5 . 生产环境 尽量 禁止直接TRUNCATE 操作 ,审批 + 审核确认

 

3.3 数据恢复优先级决策树

遇到数据丢失时,按以下顺序选择恢复方案:

DML 误操作( UPDATE/DELETE ):

   → 闪回查询( Flashback Query )

   → 闪回表( Flashback Table )

   → LogMiner 分析 redo 日志,获取 SQL_UNDO

   → RMAN 备份异机恢复

 

TRUNCATE 误操作:

   → 容灾库闪回数据库 + dblink 回传(首选)

   → RMAN 异机恢复(有备份时)

   → FY_RECOVER_DATA 存储过程包

   → 第三方工具( ODU/DUL/PRM )

 

DROP TABLE :

   → 闪回 DROP ( Recycle Bin )

   → RMAN 备份恢复

   → 第三方工具

 

好了,今天的内容就到这里。LogMiner、闪回数据库、RMAN异机恢复、FY_RECOVER_DATA、第三方工具——这篇文章把TRUNCATE数据恢复从头到尾扒了个遍。如果你在生产环境中经历过数据恢复的实战,欢迎在评论区分享你的经验和踩过的坑。遇到问题也可以留言,我看到都会回。 (如果有读者需要 FY_RECOVER_DATA , 可以关注私信我哈! )

 

我们下期见!

 

—— 睿 | Oracle性能优化老司机


来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70047128/viewspace-3175110/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
要得到你想要的某样东西,最可靠的办法是让你自己配得上它。

注册时间:2025-07-21

  • 博文量
    30
  • 访问量
    31690