首页 > 数据库 > Oracle > 闪回搞不定时怎么办?Oracle数据恢复的终极武器
Oracle数据恢复进阶实战:LogMiner日志挖掘与TRUNCATE恢复全攻略
大家好,我是睿。
上一期我们聊了Oracle闪回技术全家桶,从闪回查询到闪回数据库,把6种闪回方式全部实操了一遍。文章最后我留了个预告——当闪回技术搞不定的时候,该怎么办?
现实中,DBA经常遇到这些棘手场景:
• DML 误操作后, redo 日志已经被归档,在线日志里找不到
• 需要精确审计 " 谁在什么时间改了什么数据 "
• TRUNCATE 误删了核心业务表,闪回技术无能为力
• 没有开归档,闪回区也过期了
今天这篇文章,我们就来掌握几把终极武器:LogMiner日志挖掘和TRUNCATE后的数据恢复方案。这些是闪回之外的最后防线,每一个DBA都应该烂熟于心。
LogMiner是Oracle自带的redo日志分析工具,它能读取redo log和archive log,把二进制日志翻译成可读的SQL语句。核心能力:
• 查看 DML 操作的 SQL_REDO (重放)和 SQL_UNDO (回滚)
• 精确审计:谁、什么时间、对哪张表、做了什么操作
• 追踪数据变更历史,辅助故障定位
• 不需要额外 license ,标准版即可使用
开启补充日志(必须):
-- 开启最小补充日志( 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;
下面用一个完整的实验来演示整个流程。
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;
生产环境的日志量动辄几十上百个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%';
实际场景中,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. 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 是 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
闪回数据库是恢复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的根本原因。
如果容灾库没有开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;
表空间级恢复的速度比全库恢复快得多,但需要注意:异机的文件路径、表空间名称等可能需要调整。可控性也不如全库恢复,实际使用要根据具体情况灵活判断。
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.
如果以上方案都不可用 ——没有容灾库闪回、没有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;
1. 日常开启最小补充日志,关键时刻不掉链子
2. 重要表开启全列补充日志
3. 分析时先用时间 /SCN/ 表名精准过滤,避免 大 量扫描
4. 大量日志分析建议在 异机 库进行,不影响生产
5. 定期清理不需要的归档日志,释放空间
1. 做好用户的 权限 管理 ,只授予必要的 使用权限
2 . 容灾库务必开启 Flashback Database (关键时刻能救命)
3 . RMAN 备份策略:全备 + 增量 + 归档日志 尽量多的 保留
4 . 重要操作前记录 关键 时间 节点
5 . 生产环境 尽量 禁止直接TRUNCATE 操作 ,审批 + 审核确认
遇到数据丢失时,按以下顺序选择恢复方案:
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/ ,如需转载,请注明出处,否则将追究法律责任。