2018-04-26,KK日记,误删DBMS_LOGMNR_D.SET_TABLESPACE的表空间

一、案例

我们有一个同事,在测试环境内执行完DBMS_LOGMNR_D.SET_TABLESPACE(‘TBS1’)后,又执行了drop tablespace TBS1 INCLUDING CONTENTS AND DATAFILES;
结果导致系统包dbms_logmnr,DBMS_LOGMNR_INTERNAL,dbms_logmnr_d等不能正使用。
很不幸,测试环境我们没有备份,那应该如何处理呢?

二、问题

如何恢复dbms_logmnr,DBMS_LOGMNR_INTERNAL,dbms_logmnr_d的正常使用?

三、数据收集和分析

3.1 操作过程顾

CREATE TABLESPACE TBS1
DATAFILE '/u04/tbs101.dbf' SIZE 1g ; 

EXECUTE SYS.DBMS_LOGMNR_D.SET_TABLESPACE('TBS1');

drop tablespace tbs1 including contents and datafiles;

CREATE TABLESPACE TBS2
DATAFILE '/u04/tbs201.dbf' SIZE 1g ; 

EXECUTE SYS.DBMS_LOGMNR_D.SET_TABLESPACE('TBS2');   --这时开始报错,说DBMS_LOGMNR_INTERNAL有内部错误

分析:1. 查看DBMS_LOGMNR_INTERNAL、DBMS_LOGMNR_D、DBMS_LOGMNR状态,发现是invalid 初步猜测在set_tablespace时,将一些系统对象move到新表空间。

3.2 实验验证

  • 使用VM上的ORACLE DB
  • 事前进行备份
  • 执行SET_TABLESPACE,观察新表空间有些什么对象。
CREATE TABLESPACE TBS1
DATAFILE 
'/u01/app/oracle/oradata/db1/tbs101.dbf' SIZE 500m; 
EXECUTE SYS.DBMS_LOGMNR_D.SET_TABLESPACE('TBS1');
select owner,segment_name,segment_type from dba_segments where tablespace_name='TBS1';

有148个由logmnr开头组成的表和索引,有分区表,有LOB对象,

  • 模拟删除
drop tablespace tbs1 including contents and datafiles;
CREATE TABLESPACE TBS2
DATAFILE 
'/u01/app/oracle/oradata/db1/tbs201.dbf' SIZE 500m; 


EXECUTE SYS.DBMS_LOGMNR_D.SET_TABLESPACE('TBS2');


SQL> EXECUTE SYS.DBMS_LOGMNR_D.SET_TABLESPACE('TBS2');
BEGIN SYS.DBMS_LOGMNR_D.SET_TABLESPACE('TBS2'); END;

*
ERROR at line 1:
ORA-04063: package body "SYS.DBMS_LOGMNR_INTERNAL" has errors
ORA-06508: PL/SQL: could not find program unit being called: "SYS.DBMS_LOGMNR_INTERNAL"
ORA-06512: at "SYS.DBMS_LOGMNR_D", line 135
ORA-06512: at line 1

select * from dba_errors;

由于删除tbs1时,把一些system下logmnr开头的对象都删除了,所以在调用关联的包时表报错了。

  • 模拟恢复(support.oracle.com上提供了类似解决方案)
--shutdown the database.
shutdown immediate
--start the db
STARTUP UPGRADE
--spool to a file
SPOOL patch.log
--run the upgrade script
@?/rdbms/admin/catupgrd.sql
--turn off spooling (review file for errors)
spool off
--shutdown and restart.
shutdown immediate
startup
EXECUTE SYS.DBMS_LOGMNR_D.SET_TABLESPACE('TBS2');
-- 依样报错,信息和之前的一样,恢复失败。
  • 实验结果 恢复失败

3.3 第二次实验验证

  • 实验方案:从其它正常的库里把缺少的对象抽出DDL,重执行。
  • 模拟删除,步骤与3.2一样,就不再过多描述
  • 根据3.2观察的误删除表空间上的都是对logmnr开头的对象,于是在一个的新环境上(正常的DB)重新执行一次dbms_logmnr_d.set_tablespace('TBS1')命令,然后把该tbs1上的对象导出ddl(方法有很多,可以用imp,exp命令,或toad的export ddl,这里就不过多描述),在误删表空间上重生成一次。
  • 结果,可以正常调用dbms_logmnr包的命令,具体如下:
EXECUTE SYS.DBMS_LOGMNR_D.SET_TABLESPACE('TBS2');
EXECUTE dbms_logmnr.add_logfile(LogFileName=>'/XXXX/2018_04_26/o1_mf_1_404233_fg387zs2_.arc', Options=>dbms_logmnr.new);                                                                  
EXECUTE dbms_logmnr.start_logmnr(options=>dbms_logmnr.DICT_FROM_ONLINE_CATALOG);
EXECUTE dbms_logmnr.end_logmnr();                                                                                                                                                                                 
select * from v$logmnr_contents;
  • 成功运行没有问题。

3.4 第三次实验验证

  • 方案:将备份转移到其它机上恢复,然后执行3.3步骤。
  • 异机恢复过程与步骤也不过多描述了,这些都可以网上搜索到。
  • 验证通过,成功运行。

四、结论

  • 1.采用重运行脚本的方式基本不可行。
  • 2.如果没有备份或测试开发环境的情况下,就从异机导一份结构过来,内容可以不补充。
  • 3.如果有备份,最后恢复出来,把误删除前的表空间及内容恢复,然后用imp,exp方法导回到原库。
  • 最安全,最稳妥是3,其次是2.

五、延伸记录

alter system set utl_file_dir='/u03/' scope=spfile;
EXECUTE dbms_logmnr_d.build(  dictionary_filename => 'logminer_test.dat',  dictionary_location => '/u03/'); 
BEGIN SYS.DBMS_LOGMNR.START_LOGMNR( STARTSCN => 11886853829776,  OPTIONS =>    DBMS_LOGMNR.DICT_FROM_REDO_LOGS+SYS.DBMS_LOGMNR.DDL_DICT_TRACKING +  SYS.DBMS_LOGMNR.CONTINUOUS_MINE);  END; --如果不执行12命令,会报字典不存在。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值