Oracle利用 RMAN + ArchiveLog + LogMiner 找回误 DELETE 数据

Oracle 实战:利用 RMAN + ArchiveLog + LogMiner 找回误 DELETE 数据

问题背景

线上数据库发生了误删除(DELETE)数据,但由于 RMAN 全量备份已经在清理周期后被清理,备份片不完整无法直接恢复数据库数据。并因此无法直接通过已有备份进行RMAN还原。

最终采用以下方案完成数据恢复:

找回备份的 ArchiveLog → RMAN Catalog 注册 → Restore ArchiveLog → LogMiner 挖掘日志 → 获取 SQL_UNDO → 恢复误删除数据

整个恢复流程如下:

text 复制代码
确认误删除时间
        │
        ▼
查询归档日志 Sequence
        │
        ▼
恢复缺失 ArchiveLog
        │
        ▼
LogMiner 挖掘归档日志
        │
        ▼
找到 DELETE 操作
        │
        ▼
获取 SQL_UNDO
        │
        ▼
执行 Undo SQL 恢复数据

一、确定误删除时间

首先需要确认数据删除的大概时间。

例如:

复制代码
2026-06-18 02:50:50
~
2026-06-18 18:00:50

时间范围越准确,后续日志挖掘效率越高。


二、查询对应 ArchiveLog Sequence

先确认当天涉及哪些归档日志。

sql 复制代码
SELECT *
FROM v$archived_log a
WHERE a.FIRST_TIME >= TO_DATE('2026-06-18','yyyy-mm-dd')
AND a.FIRST_TIME < TO_DATE('2026-06-19','yyyy-mm-dd');

记录对应的:

  • Sequence#
  • Thread#
  • FIRST_TIME
  • NEXT_TIME

后续恢复归档日志需要使用对应的 Sequence。


三、恢复缺失的 ArchiveLog

由于数据库中的归档已经不存在,需要从备份中恢复。

1、Catalog 备份文件

将备份文件注册到 RMAN。

rman 复制代码
catalog backuppiece '/home/oracle/arch_20260619_5b4r14ep_1_1';

catalog backuppiece '/home/oracle/arch_20260619_594r14ep_1_1';

catalog backuppiece '/home/oracle/arch_20260619_5c4r14ep_1_1';

catalog backuppiece '/home/oracle/arch_20260619_5a4r14ep_1_1';

catalog backuppiece '/home/oracle/arch_20260619_584r14ep_1_1';

catalog backuppiece '/home/oracle/arch_20260619_5t4r16b5_1_1';

注册成功后会看到类似输出:

text 复制代码
cataloged backup piece
RECID=100541
STAMP=1236954536

2、恢复指定 Sequence 的归档日志

rman 复制代码
run {
    set archivelog destination to '/home/oracle/archivelog-restore';

    restore archivelog
    from sequence 285410
    until sequence 285421
    thread 1;
}

恢复完成后,会得到对应的 ArchiveLog 文件。

例如:

复制代码
/home/oracle/archivelog-restore/1_285421_929291329.dbf

四、使用 LogMiner 挖掘归档日志

1、加载归档日志

sql 复制代码
BEGIN
    DBMS_LOGMNR.ADD_LOGFILE(
        LOGFILENAME => '/home/oracle/archivelog-restore/1_285421_929291329.dbf',
        OPTIONS => DBMS_LOGMNR.NEW
    );
END;
/

查看当前加载的日志:

sql 复制代码
SELECT filename
FROM v$logmnr_logs;

2、启动 LogMiner

sql 复制代码
BEGIN
    DBMS_LOGMNR.START_LOGMNR(
        OPTIONS => DBMS_LOGMNR.DICT_FROM_ONLINE_CATALOG
    );
END;
/

3、查询指定表的操作记录

例如查询:

复制代码
am_studentcontact
sql 复制代码
SELECT
    x.TIMESTAMP,
    x.TABLE_NAME,
    x.SQL_REDO,
    x.SQL_UNDO
FROM v$logmnr_contents x
WHERE x.TIMESTAMP >= TO_DATE(
        '2026-06-18 02:50:50',
        'yyyy-MM-dd hh24:mi:ss'
      )
AND x.TIMESTAMP < TO_DATE(
        '2026-06-18 18:00:50',
        'yyyy-MM-dd hh24:mi:ss'
      )
AND x.TABLE_NAME = UPPER('am_studentcontact')
ORDER BY x.TIMESTAMP;

查询结果中重点关注:

  • SQL_REDO
  • SQL_UNDO

例如:

复制代码
SQL_REDO

DELETE FROM AM_STUDENTCONTACT WHERE ID='1001';

对应会生成:

复制代码
SQL_UNDO

INSERT INTO AM_STUDENTCONTACT(...)
VALUES(...);

这就是恢复数据所需要执行的 SQL。


4、结束 LogMiner

sql 复制代码
BEGIN
    DBMS_LOGMNR.END_LOGMNR;
END;
/

如此重复,解析整个时间段内的多个archivelog,得到当天DELETE的所有SQL记录。

五、执行 SQL_UNDO 恢复数据

找到对应删除操作后,直接执行:

sql 复制代码
SQL_UNDO

即可恢复误删除的数据。

相比整库恢复,这种方式:

  • 不影响业务
  • 不需要恢复整个数据库
  • 可以精准恢复单条或单表数据

整个恢复思路总结

text 复制代码
误 DELETE 数据
      │
      ▼
确定误删除时间
      │
      ▼
查询 ArchiveLog Sequence
      │
      ▼
发现归档已不存在
      │
      ▼
找到备份 ArchiveLog
      │
      ▼
RMAN Catalog 注册
      │
      ▼
Restore ArchiveLog
      │
      ▼
LogMiner 挖掘日志
      │
      ▼
找到 SQL_UNDO
      │
      ▼
执行 Undo SQL
      │
      ▼
数据恢复完成